Browse Source

feat: update tree

pull/225/head
tangjinzhou 6 years ago
parent
commit
c7ab23c4ce
  1. 43
      components/index.js
  2. 22
      components/tree/DirectoryTree.jsx
  3. 8
      components/tree/Tree.jsx
  4. 139
      components/tree/__tests__/__snapshots__/demo.test.js.snap
  5. 38
      components/tree/__tests__/util.test.js
  6. 43
      components/tree/demo/directory.md
  7. 4
      components/tree/demo/index.vue
  8. 14
      components/tree/demo/search.md
  9. 3
      components/tree/index.jsx
  10. 183
      components/tree/index.old.jsx
  11. 4
      components/tree/util.js
  12. 8
      components/vc-tree/src/Tree.jsx
  13. 17
      components/vc-tree/src/TreeNode.jsx
  14. 378
      components/vc-tree/src/util.1.js

43
components/index.js

@ -125,101 +125,60 @@ import { default as Drawer } from './drawer'
const components = [ const components = [
Affix, Affix,
Anchor, Anchor,
Anchor.Link,
AutoComplete, AutoComplete,
AutoComplete.Option,
AutoComplete.OptGroup,
Alert, Alert,
Avatar, Avatar,
BackTop, BackTop,
Badge, Badge,
Breadcrumb, Breadcrumb,
Breadcrumb.Item,
Button, Button,
Button.Group,
Calendar, Calendar,
Card, Card,
Card.Meta,
Card.Grid,
Collapse, Collapse,
Collapse.Panel,
Carousel, Carousel,
Cascader, Cascader,
Checkbox, Checkbox,
Checkbox.Group,
Col, Col,
DatePicker, DatePicker,
DatePicker.MonthPicker,
DatePicker.RangePicker,
DatePicker.WeekPicker,
Divider, Divider,
Dropdown, Dropdown,
Dropdown.Button,
Form, Form,
Form.Item,
Icon, Icon,
Input, Input,
Input.Group,
Input.Search,
Input.TextArea,
InputNumber, InputNumber,
Layout, Layout,
Layout.Header,
Layout.Footer,
Layout.Sider,
Layout.Content,
List, List,
List.Item,
List.Item.Meta,
LocaleProvider, LocaleProvider,
Menu, Menu,
Menu.Item,
Menu.SubMenu,
Menu.Divider,
Menu.ItemGroup,
Modal, Modal,
Pagination, Pagination,
Popconfirm, Popconfirm,
Popover, Popover,
Progress, Progress,
Radio, Radio,
Radio.Group,
Radio.Button,
Rate, Rate,
Row, Row,
Select, Select,
Select.Option,
Select.OptGroup,
Slider, Slider,
Spin, Spin,
Steps, Steps,
Steps.Step,
Switch, Switch,
Table, Table,
Table.Column,
Table.ColumnGroup,
Transfer, Transfer,
Tree, Tree,
Tree.TreeNode,
TreeSelect, TreeSelect,
TreeSelect.TreeNode,
Tabs, Tabs,
Tabs.TabPane,
Tabs.TabContent,
Tag, Tag,
Tag.CheckableTag,
TimePicker, TimePicker,
Timeline, Timeline,
Timeline.Item,
Tooltip, Tooltip,
Upload, Upload,
Upload.Dragger,
Drawer, Drawer,
] ]
const install = function (Vue) { const install = function (Vue) {
components.map(component => { components.map(component => {
Vue.component(component.name, component) Vue.use(component)
}) })
Vue.prototype.$message = message Vue.prototype.$message = message

22
components/tree/DirectoryTree.jsx

@ -5,6 +5,7 @@ import { conductExpandParent, convertTreeToEntities } from '../vc-tree/src/util'
import Tree, { TreeProps } from './Tree' import Tree, { TreeProps } from './Tree'
import { calcRangeKeys, getFullKeyList } from './util' import { calcRangeKeys, getFullKeyList } from './util'
import Icon from '../icon' import Icon from '../icon'
import BaseMixin from '../_util/BaseMixin'
import { initDefaultProps, getOptionProps } from '../_util/props-util' import { initDefaultProps, getOptionProps } from '../_util/props-util'
// export type ExpandAction = false | 'click' | 'doubleClick'; // export type ExpandAction = false | 'click' | 'doubleClick';
@ -27,12 +28,13 @@ function getIcon (h, props) {
} }
export default { export default {
mixins: [BaseMixin],
name: 'ADirectoryTree', name: 'ADirectoryTree',
model: { model: {
prop: 'checkedKeys', prop: 'checkedKeys',
event: 'check', event: 'check',
}, },
props: initDefaultProps({ ...TreeProps(), expandAction: PropTypes.oneOf([false, 'click', 'doubleClick']) }, { props: initDefaultProps({ ...TreeProps(), expandAction: PropTypes.oneOf([false, 'click', 'doubleclick']) }, {
prefixCls: 'ant-tree', prefixCls: 'ant-tree',
showIcon: true, showIcon: true,
expandAction: 'click', expandAction: 'click',
@ -55,7 +57,7 @@ export default {
// Expanded keys // Expanded keys
if (defaultExpandAll) { if (defaultExpandAll) {
state._expandedKeys = getFullKeyList(props.children) state._expandedKeys = getFullKeyList(this.$slots.default)
} else if (defaultExpandParent) { } else if (defaultExpandParent) {
state._expandedKeys = conductExpandParent(expandedKeys || defaultExpandedKeys, keyEntities) state._expandedKeys = conductExpandParent(expandedKeys || defaultExpandedKeys, keyEntities)
} else { } else {
@ -102,7 +104,7 @@ export default {
const { expandAction } = this.$props const { expandAction } = this.$props
// Expand the tree // Expand the tree
if (expandAction === 'doubleClick') { if (expandAction === 'doubleclick') {
this.onDebounceExpand(event, node) this.onDebounceExpand(event, node)
} }
@ -117,7 +119,6 @@ export default {
const { eventKey = '' } = node const { eventKey = '' } = node
const newState = {} const newState = {}
// Windows / Mac single pick // Windows / Mac single pick
const ctrlPick = nativeEvent.ctrlKey || nativeEvent.metaKey const ctrlPick = nativeEvent.ctrlKey || nativeEvent.metaKey
const shiftPick = nativeEvent.shiftKey const shiftPick = nativeEvent.shiftKey
@ -171,7 +172,7 @@ export default {
this.$emit('expand', newExpandedKeys, { this.$emit('expand', newExpandedKeys, {
expanded: !expanded, expanded: !expanded,
node, node,
nativeEvent: event.nativeEvent, nativeEvent: event,
}) })
}, },
@ -195,10 +196,13 @@ export default {
selectedKeys, selectedKeys,
}, },
class: `${prefixCls}-directory`, class: `${prefixCls}-directory`,
select: this.onSelect, on: {
click: this.onClick, ...this.$listeners,
doubleclick: this.onDoubleClick, select: this.onSelect,
expand: this.onExpand, click: this.onClick,
doubleclick: this.onDoubleClick,
expand: this.onExpand,
},
} }
return ( return (
<Tree {...treeProps}>{this.$slots.default}</Tree> <Tree {...treeProps}>{this.$slots.default}</Tree>

8
components/tree/Tree.jsx

@ -113,12 +113,8 @@ export default {
const { children, on = {}, slots = {}, scopedSlots = {}, key, class: cls, style, ...restProps } = item const { children, on = {}, slots = {}, scopedSlots = {}, key, class: cls, style, ...restProps } = item
const treeNodeProps = { const treeNodeProps = {
...restProps, ...restProps,
icon: restProps.icon || icon: $slots[slots.icon] || ($scopedSlots[scopedSlots.icon] && $scopedSlots[scopedSlots.icon]) || restProps.icon,
$slots[slots.icon] || title: $slots[slots.title] || ($scopedSlots[scopedSlots.title] && $scopedSlots[scopedSlots.title](item)) || restProps.title,
($scopedSlots[scopedSlots.icon] && $scopedSlots[scopedSlots.icon]),
title: restProps.title ||
$slots[slots.title] ||
($scopedSlots[scopedSlots.title] && $scopedSlots[scopedSlots.title])(item),
dataRef: item, dataRef: item,
on, on,
key, key,

139
components/tree/__tests__/__snapshots__/demo.test.js.snap

@ -1,18 +1,18 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP // Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`renders ./components/tree/demo/basic.md correctly 1`] = ` exports[`renders ./components/tree/demo/basic.md correctly 1`] = `
<ul role="tree-node" unselectable="on" class="ant-tree"> <ul role="tree" unselectable="on" class="ant-tree ant-tree-icon-hide">
<li class="ant-tree-treenode-switcher-open ant-tree-treenode-checkbox-checked"><span class="ant-tree-switcher ant-tree-switcher_open"></span><span class="ant-tree-checkbox ant-tree-checkbox-checked"><span class="ant-tree-checkbox-inner"></span></span><span title="parent 1" class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-open"><span class="ant-tree-title">parent 1</span></span> <li role="treeitem" class="ant-tree-treenode-switcher-open ant-tree-treenode-checkbox-checked"><span class="ant-tree-switcher ant-tree-switcher_open"></span><span class="ant-tree-checkbox ant-tree-checkbox-checked"><span class="ant-tree-checkbox-inner"></span></span><span title="parent 1" class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-open"><span class="ant-tree-title">parent 1</span></span>
<ul data-expanded="true" class="ant-tree-child-tree ant-tree-child-tree-open"> <ul data-expanded="true" role="group" class="ant-tree-child-tree ant-tree-child-tree-open">
<li class="ant-tree-treenode-disabled ant-tree-treenode-switcher-open ant-tree-treenode-checkbox-checked ant-tree-treenode-selected"><span class="ant-tree-switcher ant-tree-switcher_open"></span><span class="ant-tree-checkbox ant-tree-checkbox-checked ant-tree-checkbox-disabled"><span class="ant-tree-checkbox-inner"></span></span><span title="parent 1-0" class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-open"><span class="ant-tree-title">parent 1-0</span></span> <li role="treeitem" class="ant-tree-treenode-disabled ant-tree-treenode-switcher-open ant-tree-treenode-checkbox-checked ant-tree-treenode-selected"><span class="ant-tree-switcher ant-tree-switcher_open"></span><span class="ant-tree-checkbox ant-tree-checkbox-checked ant-tree-checkbox-disabled"><span class="ant-tree-checkbox-inner"></span></span><span title="parent 1-0" class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-open"><span class="ant-tree-title">parent 1-0</span></span>
<ul data-expanded="true" class="ant-tree-child-tree ant-tree-child-tree-open"> <ul data-expanded="true" role="group" class="ant-tree-child-tree ant-tree-child-tree-open">
<li class="ant-tree-treenode-switcher-close"><span class="ant-tree-switcher ant-tree-switcher-noop"></span><span class="ant-tree-checkbox ant-tree-checkbox-disabled"><span class="ant-tree-checkbox-inner"></span></span><span title="leaf" class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-normal"><span class="ant-tree-title">leaf</span></span></li> <li role="treeitem" class="ant-tree-treenode-switcher-close"><span class="ant-tree-switcher ant-tree-switcher-noop"></span><span class="ant-tree-checkbox ant-tree-checkbox-disabled"><span class="ant-tree-checkbox-inner"></span></span><span title="leaf" class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-normal"><span class="ant-tree-title">leaf</span></span></li>
<li class="ant-tree-treenode-switcher-close"><span class="ant-tree-switcher ant-tree-switcher-noop"></span><span class="ant-tree-checkbox"><span class="ant-tree-checkbox-inner"></span></span><span title="leaf" class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-normal"><span class="ant-tree-title">leaf</span></span></li> <li role="treeitem" class="ant-tree-treenode-switcher-close"><span class="ant-tree-switcher ant-tree-switcher-noop"></span><span class="ant-tree-checkbox"><span class="ant-tree-checkbox-inner"></span></span><span title="leaf" class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-normal"><span class="ant-tree-title">leaf</span></span></li>
</ul> </ul>
</li> </li>
<li class="ant-tree-treenode-switcher-open ant-tree-treenode-checkbox-checked"><span class="ant-tree-switcher ant-tree-switcher_open"></span><span class="ant-tree-checkbox ant-tree-checkbox-checked"><span class="ant-tree-checkbox-inner"></span></span><span title="parent 1-1" class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-open"><span class="ant-tree-title">parent 1-1</span></span> <li role="treeitem" class="ant-tree-treenode-switcher-open ant-tree-treenode-checkbox-checked"><span class="ant-tree-switcher ant-tree-switcher_open"></span><span class="ant-tree-checkbox ant-tree-checkbox-checked"><span class="ant-tree-checkbox-inner"></span></span><span title="parent 1-1" class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-open"><span class="ant-tree-title">parent 1-1</span></span>
<ul data-expanded="true" class="ant-tree-child-tree ant-tree-child-tree-open"> <ul data-expanded="true" role="group" class="ant-tree-child-tree ant-tree-child-tree-open">
<li class="ant-tree-treenode-switcher-close ant-tree-treenode-checkbox-checked"><span class="ant-tree-switcher ant-tree-switcher-noop"></span><span class="ant-tree-checkbox ant-tree-checkbox-checked"><span class="ant-tree-checkbox-inner"></span></span><span title="" class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-normal"><span class="ant-tree-title"><span style="color: rgb(24, 144, 255);">sss</span></span></span></li> <li role="treeitem" class="ant-tree-treenode-switcher-close ant-tree-treenode-checkbox-checked"><span class="ant-tree-switcher ant-tree-switcher-noop"></span><span class="ant-tree-checkbox ant-tree-checkbox-checked"><span class="ant-tree-checkbox-inner"></span></span><span title="" class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-normal"><span class="ant-tree-title"><span style="color: rgb(24, 144, 255);">sss</span></span></span></li>
</ul> </ul>
</li> </li>
</ul> </ul>
@ -21,91 +21,108 @@ exports[`renders ./components/tree/demo/basic.md correctly 1`] = `
`; `;
exports[`renders ./components/tree/demo/basic-controlled.md correctly 1`] = ` exports[`renders ./components/tree/demo/basic-controlled.md correctly 1`] = `
<ul role="tree-node" unselectable="on" class="ant-tree"> <ul role="tree" unselectable="on" class="ant-tree ant-tree-icon-hide">
<li class="ant-tree-treenode-switcher-open ant-tree-treenode-checkbox-indeterminate"><span class="ant-tree-switcher ant-tree-switcher_open"></span><span class="ant-tree-checkbox ant-tree-checkbox-indeterminate"><span class="ant-tree-checkbox-inner"></span></span><span title="0-0" class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-open"><span class="ant-tree-title">0-0</span></span> <li role="treeitem" class="ant-tree-treenode-switcher-open ant-tree-treenode-checkbox-indeterminate"><span class="ant-tree-switcher ant-tree-switcher_open"></span><span class="ant-tree-checkbox ant-tree-checkbox-indeterminate"><span class="ant-tree-checkbox-inner"></span></span><span title="0-0" class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-open"><span class="ant-tree-title">0-0</span></span>
<ul data-expanded="true" class="ant-tree-child-tree ant-tree-child-tree-open"> <ul data-expanded="true" role="group" class="ant-tree-child-tree ant-tree-child-tree-open">
<li class="ant-tree-treenode-switcher-open ant-tree-treenode-checkbox-checked"><span class="ant-tree-switcher ant-tree-switcher_open"></span><span class="ant-tree-checkbox ant-tree-checkbox-checked"><span class="ant-tree-checkbox-inner"></span></span><span title="0-0-0" class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-open"><span class="ant-tree-title">0-0-0</span></span> <li role="treeitem" class="ant-tree-treenode-switcher-open ant-tree-treenode-checkbox-checked"><span class="ant-tree-switcher ant-tree-switcher_open"></span><span class="ant-tree-checkbox ant-tree-checkbox-checked"><span class="ant-tree-checkbox-inner"></span></span><span title="0-0-0" class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-open"><span class="ant-tree-title">0-0-0</span></span>
<ul data-expanded="true" class="ant-tree-child-tree ant-tree-child-tree-open"> <ul data-expanded="true" role="group" class="ant-tree-child-tree ant-tree-child-tree-open">
<li class="ant-tree-treenode-switcher-close ant-tree-treenode-checkbox-checked"><span class="ant-tree-switcher ant-tree-switcher-noop"></span><span class="ant-tree-checkbox ant-tree-checkbox-checked"><span class="ant-tree-checkbox-inner"></span></span><span title="0-0-0-0" class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-normal"><span class="ant-tree-title">0-0-0-0</span></span></li> <li role="treeitem" class="ant-tree-treenode-switcher-close ant-tree-treenode-checkbox-checked"><span class="ant-tree-switcher ant-tree-switcher-noop"></span><span class="ant-tree-checkbox ant-tree-checkbox-checked"><span class="ant-tree-checkbox-inner"></span></span><span title="0-0-0-0" class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-normal"><span class="ant-tree-title">0-0-0-0</span></span></li>
<li class="ant-tree-treenode-switcher-close ant-tree-treenode-checkbox-checked"><span class="ant-tree-switcher ant-tree-switcher-noop"></span><span class="ant-tree-checkbox ant-tree-checkbox-checked"><span class="ant-tree-checkbox-inner"></span></span><span title="0-0-0-1" class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-normal"><span class="ant-tree-title">0-0-0-1</span></span></li> <li role="treeitem" class="ant-tree-treenode-switcher-close ant-tree-treenode-checkbox-checked"><span class="ant-tree-switcher ant-tree-switcher-noop"></span><span class="ant-tree-checkbox ant-tree-checkbox-checked"><span class="ant-tree-checkbox-inner"></span></span><span title="0-0-0-1" class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-normal"><span class="ant-tree-title">0-0-0-1</span></span></li>
<li class="ant-tree-treenode-switcher-close ant-tree-treenode-checkbox-checked"><span class="ant-tree-switcher ant-tree-switcher-noop"></span><span class="ant-tree-checkbox ant-tree-checkbox-checked"><span class="ant-tree-checkbox-inner"></span></span><span title="0-0-0-2" class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-normal"><span class="ant-tree-title">0-0-0-2</span></span></li> <li role="treeitem" class="ant-tree-treenode-switcher-close ant-tree-treenode-checkbox-checked"><span class="ant-tree-switcher ant-tree-switcher-noop"></span><span class="ant-tree-checkbox ant-tree-checkbox-checked"><span class="ant-tree-checkbox-inner"></span></span><span title="0-0-0-2" class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-normal"><span class="ant-tree-title">0-0-0-2</span></span></li>
</ul> </ul>
</li> </li>
<li class="ant-tree-treenode-switcher-open"><span class="ant-tree-switcher ant-tree-switcher_open"></span><span class="ant-tree-checkbox"><span class="ant-tree-checkbox-inner"></span></span><span title="0-0-1" class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-open"><span class="ant-tree-title">0-0-1</span></span> <li role="treeitem" class="ant-tree-treenode-switcher-open"><span class="ant-tree-switcher ant-tree-switcher_open"></span><span class="ant-tree-checkbox"><span class="ant-tree-checkbox-inner"></span></span><span title="0-0-1" class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-open"><span class="ant-tree-title">0-0-1</span></span>
<ul data-expanded="true" class="ant-tree-child-tree ant-tree-child-tree-open"> <ul data-expanded="true" role="group" class="ant-tree-child-tree ant-tree-child-tree-open">
<li class="ant-tree-treenode-switcher-close"><span class="ant-tree-switcher ant-tree-switcher-noop"></span><span class="ant-tree-checkbox"><span class="ant-tree-checkbox-inner"></span></span><span title="0-0-1-0" class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-normal"><span class="ant-tree-title">0-0-1-0</span></span></li> <li role="treeitem" class="ant-tree-treenode-switcher-close"><span class="ant-tree-switcher ant-tree-switcher-noop"></span><span class="ant-tree-checkbox"><span class="ant-tree-checkbox-inner"></span></span><span title="0-0-1-0" class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-normal"><span class="ant-tree-title">0-0-1-0</span></span></li>
<li class="ant-tree-treenode-switcher-close"><span class="ant-tree-switcher ant-tree-switcher-noop"></span><span class="ant-tree-checkbox"><span class="ant-tree-checkbox-inner"></span></span><span title="0-0-1-1" class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-normal"><span class="ant-tree-title">0-0-1-1</span></span></li> <li role="treeitem" class="ant-tree-treenode-switcher-close"><span class="ant-tree-switcher ant-tree-switcher-noop"></span><span class="ant-tree-checkbox"><span class="ant-tree-checkbox-inner"></span></span><span title="0-0-1-1" class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-normal"><span class="ant-tree-title">0-0-1-1</span></span></li>
<li class="ant-tree-treenode-switcher-close"><span class="ant-tree-switcher ant-tree-switcher-noop"></span><span class="ant-tree-checkbox"><span class="ant-tree-checkbox-inner"></span></span><span title="0-0-1-2" class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-normal"><span class="ant-tree-title">0-0-1-2</span></span></li> <li role="treeitem" class="ant-tree-treenode-switcher-close"><span class="ant-tree-switcher ant-tree-switcher-noop"></span><span class="ant-tree-checkbox"><span class="ant-tree-checkbox-inner"></span></span><span title="0-0-1-2" class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-normal"><span class="ant-tree-title">0-0-1-2</span></span></li>
</ul> </ul>
</li> </li>
<li class="ant-tree-treenode-switcher-close"><span class="ant-tree-switcher ant-tree-switcher-noop"></span><span class="ant-tree-checkbox"><span class="ant-tree-checkbox-inner"></span></span><span title="0-0-2" class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-normal"><span class="ant-tree-title">0-0-2</span></span></li> <li role="treeitem" class="ant-tree-treenode-switcher-close"><span class="ant-tree-switcher ant-tree-switcher-noop"></span><span class="ant-tree-checkbox"><span class="ant-tree-checkbox-inner"></span></span><span title="0-0-2" class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-normal"><span class="ant-tree-title">0-0-2</span></span></li>
</ul> </ul>
</li> </li>
<li class="ant-tree-treenode-switcher-close"><span class="ant-tree-switcher ant-tree-switcher_close"></span><span class="ant-tree-checkbox"><span class="ant-tree-checkbox-inner"></span></span><span title="0-1" class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-close"><span class="ant-tree-title">0-1</span></span> <li role="treeitem" class="ant-tree-treenode-switcher-close"><span class="ant-tree-switcher ant-tree-switcher_close"></span><span class="ant-tree-checkbox"><span class="ant-tree-checkbox-inner"></span></span><span title="0-1" class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-close"><span class="ant-tree-title">0-1</span></span>
<!----> <!---->
</li> </li>
<li class="ant-tree-treenode-switcher-close"><span class="ant-tree-switcher ant-tree-switcher-noop"></span><span class="ant-tree-checkbox"><span class="ant-tree-checkbox-inner"></span></span><span title="0-2" class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-normal"><span class="ant-tree-title">0-2</span></span></li> <li role="treeitem" class="ant-tree-treenode-switcher-close"><span class="ant-tree-switcher ant-tree-switcher-noop"></span><span class="ant-tree-checkbox"><span class="ant-tree-checkbox-inner"></span></span><span title="0-2" class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-normal"><span class="ant-tree-title">0-2</span></span></li>
</ul> </ul>
`; `;
exports[`renders ./components/tree/demo/customized-icon.md correctly 1`] = ` exports[`renders ./components/tree/demo/customized-icon.md correctly 1`] = `
<ul role="tree-node" unselectable="on" class="ant-tree"> <ul role="tree" unselectable="on" class="ant-tree">
<li class="ant-tree-treenode-switcher-open"><span class="ant-tree-switcher ant-tree-switcher_open"></span><span title="parent 1" class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-open"><span class="ant-tree-iconEle ant-tree-icon__customize"><i class="anticon anticon-smile-o"></i></span><span class="ant-tree-title">parent 1</span></span> <li role="treeitem" class="ant-tree-treenode-switcher-open"><span class="ant-tree-switcher ant-tree-switcher_open"></span><span title="parent 1" class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-open"><span class="ant-tree-iconEle ant-tree-icon__customize"><i class="anticon anticon-smile-o"></i></span><span class="ant-tree-title">parent 1</span></span>
<ul data-expanded="true" class="ant-tree-child-tree ant-tree-child-tree-open"> <ul data-expanded="true" role="group" class="ant-tree-child-tree ant-tree-child-tree-open">
<li class="ant-tree-treenode-switcher-open ant-tree-treenode-selected"><span class="ant-tree-switcher ant-tree-switcher-noop"></span><span title="leaf" class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-normal ant-tree-node-selected"><span class="ant-tree-iconEle ant-tree-icon__customize"><i class="anticon anticon-smile-o"></i></span><span class="ant-tree-title">leaf</span></span></li> <li role="treeitem" class="ant-tree-treenode-switcher-open ant-tree-treenode-selected"><span class="ant-tree-switcher ant-tree-switcher-noop"></span><span title="leaf" class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-normal ant-tree-node-selected"><span class="ant-tree-iconEle ant-tree-icon__customize"><i class="anticon anticon-smile-o"></i></span><span class="ant-tree-title">leaf</span></span></li>
<li class="ant-tree-treenode-switcher-open"><span class="ant-tree-switcher ant-tree-switcher-noop"></span><span title="leaf" class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-normal"><span class="ant-tree-iconEle ant-tree-icon__customize"><i class="anticon anticon-frown-o"></i></span><span class="ant-tree-title">leaf</span></span></li> <li role="treeitem" class="ant-tree-treenode-switcher-open"><span class="ant-tree-switcher ant-tree-switcher-noop"></span><span title="leaf" class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-normal"><span class="ant-tree-iconEle ant-tree-icon__customize"><i class="anticon anticon-frown-o"></i></span><span class="ant-tree-title">leaf</span></span></li>
</ul>
</li>
</ul>
`;
exports[`renders ./components/tree/demo/directory.md correctly 1`] = `
<ul role="tree" unselectable="on" class="ant-tree ant-tree-directory">
<li role="treeitem" class="ant-tree-treenode-switcher-open"><span class="ant-tree-switcher ant-tree-switcher_open"></span><span title="parent 0" class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-open"><span class="ant-tree-iconEle ant-tree-icon__customize"><i class="anticon anticon-folder-open"></i></span><span class="ant-tree-title">parent 0</span></span>
<ul data-expanded="true" role="group" class="ant-tree-child-tree ant-tree-child-tree-open">
<li role="treeitem" class=""><span class="ant-tree-switcher ant-tree-switcher-noop"></span><span title="leaf 0-0" class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-normal"><span class="ant-tree-iconEle ant-tree-icon__customize"><i class="anticon anticon-file"></i></span><span class="ant-tree-title">leaf 0-0</span></span></li>
<li role="treeitem" class=""><span class="ant-tree-switcher ant-tree-switcher-noop"></span><span title="leaf 0-1" class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-normal"><span class="ant-tree-iconEle ant-tree-icon__customize"><i class="anticon anticon-file"></i></span><span class="ant-tree-title">leaf 0-1</span></span></li>
</ul>
</li>
<li role="treeitem" class="ant-tree-treenode-switcher-open"><span class="ant-tree-switcher ant-tree-switcher_open"></span><span title="parent 1" class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-open"><span class="ant-tree-iconEle ant-tree-icon__customize"><i class="anticon anticon-folder-open"></i></span><span class="ant-tree-title">parent 1</span></span>
<ul data-expanded="true" role="group" class="ant-tree-child-tree ant-tree-child-tree-open">
<li role="treeitem" class=""><span class="ant-tree-switcher ant-tree-switcher-noop"></span><span title="leaf 1-0" class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-normal"><span class="ant-tree-iconEle ant-tree-icon__customize"><i class="anticon anticon-file"></i></span><span class="ant-tree-title">leaf 1-0</span></span></li>
<li role="treeitem" class=""><span class="ant-tree-switcher ant-tree-switcher-noop"></span><span title="leaf 1-1" class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-normal"><span class="ant-tree-iconEle ant-tree-icon__customize"><i class="anticon anticon-file"></i></span><span class="ant-tree-title">leaf 1-1</span></span></li>
</ul> </ul>
</li> </li>
</ul> </ul>
`; `;
exports[`renders ./components/tree/demo/draggable.md correctly 1`] = ` exports[`renders ./components/tree/demo/draggable.md correctly 1`] = `
<ul role="tree-node" unselectable="on" class="draggable-tree ant-tree"> <ul role="tree" unselectable="on" class="draggable-tree ant-tree ant-tree-icon-hide">
<li class="ant-tree-treenode-switcher-open"><span class="ant-tree-switcher ant-tree-switcher_open"></span><span title="0-0" draggable="true" aria-grabbed="true" class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-open draggable"><span class="ant-tree-title">0-0</span></span> <li role="treeitem" class="ant-tree-treenode-switcher-open"><span class="ant-tree-switcher ant-tree-switcher_open"></span><span title="0-0" draggable="true" aria-grabbed="true" class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-open draggable"><span class="ant-tree-title">0-0</span></span>
<ul data-expanded="true" class="ant-tree-child-tree ant-tree-child-tree-open"> <ul data-expanded="true" role="group" class="ant-tree-child-tree ant-tree-child-tree-open">
<li class="ant-tree-treenode-switcher-open"><span class="ant-tree-switcher ant-tree-switcher_open"></span><span title="0-0-0" draggable="true" aria-grabbed="true" class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-open draggable"><span class="ant-tree-title">0-0-0</span></span> <li role="treeitem" class="ant-tree-treenode-switcher-open"><span class="ant-tree-switcher ant-tree-switcher_open"></span><span title="0-0-0" draggable="true" aria-grabbed="true" class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-open draggable"><span class="ant-tree-title">0-0-0</span></span>
<ul data-expanded="true" class="ant-tree-child-tree ant-tree-child-tree-open"> <ul data-expanded="true" role="group" class="ant-tree-child-tree ant-tree-child-tree-open">
<li class="ant-tree-treenode-switcher-open"><span class="ant-tree-switcher ant-tree-switcher-noop"></span><span title="0-0-0-0" draggable="true" aria-grabbed="true" class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-normal draggable"><span class="ant-tree-title">0-0-0-0</span></span></li> <li role="treeitem" class="ant-tree-treenode-switcher-open"><span class="ant-tree-switcher ant-tree-switcher-noop"></span><span title="0-0-0-0" draggable="true" aria-grabbed="true" class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-normal draggable"><span class="ant-tree-title">0-0-0-0</span></span></li>
<li class="ant-tree-treenode-switcher-close"><span class="ant-tree-switcher ant-tree-switcher-noop"></span><span title="0-0-0-1" draggable="true" aria-grabbed="true" class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-normal draggable"><span class="ant-tree-title">0-0-0-1</span></span></li> <li role="treeitem" class="ant-tree-treenode-switcher-close"><span class="ant-tree-switcher ant-tree-switcher-noop"></span><span title="0-0-0-1" draggable="true" aria-grabbed="true" class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-normal draggable"><span class="ant-tree-title">0-0-0-1</span></span></li>
<li class="ant-tree-treenode-switcher-close"><span class="ant-tree-switcher ant-tree-switcher-noop"></span><span title="0-0-0-2" draggable="true" aria-grabbed="true" class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-normal draggable"><span class="ant-tree-title">0-0-0-2</span></span></li> <li role="treeitem" class="ant-tree-treenode-switcher-close"><span class="ant-tree-switcher ant-tree-switcher-noop"></span><span title="0-0-0-2" draggable="true" aria-grabbed="true" class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-normal draggable"><span class="ant-tree-title">0-0-0-2</span></span></li>
</ul> </ul>
</li> </li>
<li class="ant-tree-treenode-switcher-close"><span class="ant-tree-switcher ant-tree-switcher_close"></span><span title="0-0-1" draggable="true" aria-grabbed="true" class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-close draggable"><span class="ant-tree-title">0-0-1</span></span> <li role="treeitem" class="ant-tree-treenode-switcher-close"><span class="ant-tree-switcher ant-tree-switcher_close"></span><span title="0-0-1" draggable="true" aria-grabbed="true" class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-close draggable"><span class="ant-tree-title">0-0-1</span></span>
<!----> <!---->
</li> </li>
<li class="ant-tree-treenode-switcher-close"><span class="ant-tree-switcher ant-tree-switcher-noop"></span><span title="0-0-2" draggable="true" aria-grabbed="true" class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-normal draggable"><span class="ant-tree-title">0-0-2</span></span></li> <li role="treeitem" class="ant-tree-treenode-switcher-close"><span class="ant-tree-switcher ant-tree-switcher-noop"></span><span title="0-0-2" draggable="true" aria-grabbed="true" class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-normal draggable"><span class="ant-tree-title">0-0-2</span></span></li>
</ul> </ul>
</li> </li>
<li class="ant-tree-treenode-switcher-close"><span class="ant-tree-switcher ant-tree-switcher_close"></span><span title="0-1" draggable="true" aria-grabbed="true" class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-close draggable"><span class="ant-tree-title">0-1</span></span> <li role="treeitem" class="ant-tree-treenode-switcher-close"><span class="ant-tree-switcher ant-tree-switcher_close"></span><span title="0-1" draggable="true" aria-grabbed="true" class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-close draggable"><span class="ant-tree-title">0-1</span></span>
<!----> <!---->
</li> </li>
<li class="ant-tree-treenode-switcher-close"><span class="ant-tree-switcher ant-tree-switcher-noop"></span><span title="0-2" draggable="true" aria-grabbed="true" class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-normal draggable"><span class="ant-tree-title">0-2</span></span></li> <li role="treeitem" class="ant-tree-treenode-switcher-close"><span class="ant-tree-switcher ant-tree-switcher-noop"></span><span title="0-2" draggable="true" aria-grabbed="true" class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-normal draggable"><span class="ant-tree-title">0-2</span></span></li>
</ul> </ul>
`; `;
exports[`renders ./components/tree/demo/dynamic.md correctly 1`] = ` exports[`renders ./components/tree/demo/dynamic.md correctly 1`] = `
<ul role="tree-node" unselectable="on" class="ant-tree"> <ul role="tree" unselectable="on" class="ant-tree ant-tree-icon-hide">
<li class="ant-tree-treenode-switcher-close"><span class="ant-tree-switcher ant-tree-switcher_close"></span><span title="Expand to load" class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-close"><span class="ant-tree-title">Expand to load</span></span></li> <li role="treeitem" class="ant-tree-treenode-switcher-close"><span class="ant-tree-switcher ant-tree-switcher_close"></span><span title="Expand to load" class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-close"><span class="ant-tree-title">Expand to load</span></span></li>
<li class="ant-tree-treenode-switcher-close"><span class="ant-tree-switcher ant-tree-switcher_close"></span><span title="Expand to load" class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-close"><span class="ant-tree-title">Expand to load</span></span></li> <li role="treeitem" class="ant-tree-treenode-switcher-close"><span class="ant-tree-switcher ant-tree-switcher_close"></span><span title="Expand to load" class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-close"><span class="ant-tree-title">Expand to load</span></span></li>
<li class=""><span class="ant-tree-switcher ant-tree-switcher-noop"></span><span title="Tree Node" class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-normal"><span class="ant-tree-title">Tree Node</span></span></li> <li role="treeitem" class=""><span class="ant-tree-switcher ant-tree-switcher-noop"></span><span title="Tree Node" class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-normal"><span class="ant-tree-title">Tree Node</span></span></li>
</ul> </ul>
`; `;
exports[`renders ./components/tree/demo/line.md correctly 1`] = ` exports[`renders ./components/tree/demo/line.md correctly 1`] = `
<ul role="tree-node" unselectable="on" class="ant-tree ant-tree-show-line"> <ul role="tree" unselectable="on" class="ant-tree ant-tree-show-line ant-tree-icon-hide">
<li class="ant-tree-treenode-switcher-open"><span class="ant-tree-switcher ant-tree-switcher_open"></span><span title="" class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-open"><span class="ant-tree-title"><span style="color: rgb(24, 144, 255);">parent 1</span></span></span> <li role="treeitem" class="ant-tree-treenode-switcher-open"><span class="ant-tree-switcher ant-tree-switcher_open"></span><span title="" class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-open"><span class="ant-tree-title"><span style="color: rgb(24, 144, 255);">parent 1</span></span></span>
<ul data-expanded="true" class="ant-tree-child-tree ant-tree-child-tree-open"> <ul data-expanded="true" role="group" class="ant-tree-child-tree ant-tree-child-tree-open">
<li class="ant-tree-treenode-switcher-open"><span class="ant-tree-switcher ant-tree-switcher_open"></span><span title="parent 1-0" class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-open"><span class="ant-tree-title">parent 1-0</span></span> <li role="treeitem" class="ant-tree-treenode-switcher-open"><span class="ant-tree-switcher ant-tree-switcher_open"></span><span title="parent 1-0" class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-open"><span class="ant-tree-title">parent 1-0</span></span>
<ul data-expanded="true" class="ant-tree-child-tree ant-tree-child-tree-open"> <ul data-expanded="true" role="group" class="ant-tree-child-tree ant-tree-child-tree-open">
<li class="ant-tree-treenode-switcher-close"><span class="ant-tree-switcher ant-tree-switcher-noop"></span><span title="leaf" class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-normal"><span class="ant-tree-title">leaf</span></span></li> <li role="treeitem" class="ant-tree-treenode-switcher-close"><span class="ant-tree-switcher ant-tree-switcher-noop"></span><span title="leaf" class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-normal"><span class="ant-tree-title">leaf</span></span></li>
<li class="ant-tree-treenode-switcher-close"><span class="ant-tree-switcher ant-tree-switcher-noop"></span><span title="leaf" class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-normal"><span class="ant-tree-title">leaf</span></span></li> <li role="treeitem" class="ant-tree-treenode-switcher-close"><span class="ant-tree-switcher ant-tree-switcher-noop"></span><span title="leaf" class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-normal"><span class="ant-tree-title">leaf</span></span></li>
<li class="ant-tree-treenode-switcher-close"><span class="ant-tree-switcher ant-tree-switcher-noop"></span><span title="leaf" class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-normal"><span class="ant-tree-title">leaf</span></span></li> <li role="treeitem" class="ant-tree-treenode-switcher-close"><span class="ant-tree-switcher ant-tree-switcher-noop"></span><span title="leaf" class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-normal"><span class="ant-tree-title">leaf</span></span></li>
</ul> </ul>
</li> </li>
<li class="ant-tree-treenode-switcher-close"><span class="ant-tree-switcher ant-tree-switcher_close"></span><span title="parent 1-1" class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-close"><span class="ant-tree-title">parent 1-1</span></span> <li role="treeitem" class="ant-tree-treenode-switcher-close"><span class="ant-tree-switcher ant-tree-switcher_close"></span><span title="parent 1-1" class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-close"><span class="ant-tree-title">parent 1-1</span></span>
<!----> <!---->
</li> </li>
<li class="ant-tree-treenode-switcher-close"><span class="ant-tree-switcher ant-tree-switcher_close"></span><span title="parent 1-2" class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-close"><span class="ant-tree-title">parent 1-2</span></span> <li role="treeitem" class="ant-tree-treenode-switcher-close"><span class="ant-tree-switcher ant-tree-switcher_close"></span><span title="parent 1-2" class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-close"><span class="ant-tree-title">parent 1-2</span></span>
<!----> <!---->
</li> </li>
</ul> </ul>
@ -115,22 +132,22 @@ exports[`renders ./components/tree/demo/line.md correctly 1`] = `
exports[`renders ./components/tree/demo/search.md correctly 1`] = ` exports[`renders ./components/tree/demo/search.md correctly 1`] = `
<div><span class="ant-input-search ant-input-affix-wrapper ant-input-search" style="margin-bottom: 8px;"><input placeholder="Search" type="text" class="ant-input ant-input-search"><span class="ant-input-suffix"><i class="anticon anticon-search ant-input-search-icon"></i></span></span> <div><span class="ant-input-search ant-input-affix-wrapper ant-input-search" style="margin-bottom: 8px;"><input placeholder="Search" type="text" class="ant-input ant-input-search"><span class="ant-input-suffix"><i class="anticon anticon-search ant-input-search-icon"></i></span></span>
<ul role="tree-node" unselectable="on" class="ant-tree"> <ul role="tree" unselectable="on" class="ant-tree ant-tree-icon-hide">
<li class="ant-tree-treenode-switcher-close"><span class="ant-tree-switcher ant-tree-switcher_close"></span><span title="" class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-close"><span class="ant-tree-title"><span> <li role="treeitem" class="ant-tree-treenode-switcher-close"><span class="ant-tree-switcher ant-tree-switcher_close"></span><span title="" class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-close"><span class="ant-tree-title"><span>
<span style="color: rgb(255, 85, 0);"></span> <span style="color: rgb(255, 85, 0);"></span>
0-0 0-0
</span></span></span> </span></span></span>
<!----> <!---->
</li> </li>
<li class="ant-tree-treenode-switcher-close"><span class="ant-tree-switcher ant-tree-switcher_close"></span><span title="" class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-close"><span class="ant-tree-title"><span> <li role="treeitem" class="ant-tree-treenode-switcher-close"><span class="ant-tree-switcher ant-tree-switcher_close"></span><span title="" class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-close"><span class="ant-tree-title"><span>
<span style="color: rgb(255, 85, 0);"></span> <span style="color: rgb(255, 85, 0);"></span>
0-1 0-1
</span></span></span> </span></span></span>
<!----> <!---->
</li> </li>
<li class="ant-tree-treenode-switcher-close"><span class="ant-tree-switcher ant-tree-switcher-noop"></span><span title="" class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-normal"><span class="ant-tree-title"><span> <li role="treeitem" class="ant-tree-treenode-switcher-close"><span class="ant-tree-switcher ant-tree-switcher-noop"></span><span title="" class="ant-tree-node-content-wrapper ant-tree-node-content-wrapper-normal"><span class="ant-tree-title"><span>
<span style="color: rgb(255, 85, 0);"></span> <span style="color: rgb(255, 85, 0);"></span>
0-2 0-2

38
components/tree/__tests__/util.test.js

@ -0,0 +1,38 @@
import { mount } from '@vue/test-utils'
import Tree from '../index'
import { calcRangeKeys } from '../util'
const TreeNode = Tree.TreeNode
describe('Tree util', () => {
it('calc range keys', () => {
const wrapper = mount({
render () {
return (
<Tree>
<TreeNode key='0-0'>
<TreeNode key='0-0-0' />
<TreeNode key='0-0-1' />
</TreeNode>
<TreeNode key='0-1'>
<TreeNode key='0-1-0' />
<TreeNode key='0-1-1' />
</TreeNode>
<TreeNode key='0-2'>
<TreeNode key='0-2-0'>
<TreeNode key='0-2-0-0' />
<TreeNode key='0-2-0-1' />
<TreeNode key='0-2-0-2' />
</TreeNode>
</TreeNode>
</Tree>
)
},
})
const treeWrapper = wrapper.find({ name: 'ATree' })
const keys = calcRangeKeys(treeWrapper.vm.$slots.default, ['0-0', '0-2', '0-2-0'], '0-2-0-1', '0-0-0')
const target = ['0-0-0', '0-0-1', '0-1', '0-2', '0-2-0', '0-2-0-0', '0-2-0-1']
expect(keys.sort()).toEqual(target.sort())
})
})

43
components/tree/demo/directory.md

@ -0,0 +1,43 @@
<cn>
#### 目录
内置的目录树,`multiple` 模式支持 `ctrl(Windows)` / `command(Mac)` 复选。
</cn>
<us>
#### Directory
Built-in directory tree. `multiple` support `ctrl(Windows)` / `command(Mac)` selection.
</us>
```html
<template>
<a-directory-tree
multiple
defaultExpandAll
@select="onSelect"
@expand="onExpand"
>
<a-tree-node title="parent 0" key="0-0">
<a-tree-node title="leaf 0-0" key="0-0-0" isLeaf />
<a-tree-node title="leaf 0-1" key="0-0-1" isLeaf />
</a-tree-node>
<a-tree-node title="parent 1" key="0-1">
<a-tree-node title="leaf 1-0" key="0-1-0" isLeaf />
<a-tree-node title="leaf 1-1" key="0-1-1" isLeaf />
</a-tree-node>
</a-directory-tree>
</template>
<script>
export default {
methods: {
onSelect (keys) {
console.log('Trigger Select', keys);
},
onExpand () {
console.log('Trigger Expand');
},
},
}
</script>
```

4
components/tree/demo/index.vue

@ -6,6 +6,7 @@ import Draggable from './draggable'
import Dynamic from './dynamic' import Dynamic from './dynamic'
import Line from './line' import Line from './line'
import Search from './search' import Search from './search'
import Directory from './directory'
import CN from '../index.zh-CN.md' import CN from '../index.zh-CN.md'
import US from '../index.en-US.md' import US from '../index.en-US.md'
@ -20,7 +21,7 @@ const md = {
us: `# Tree us: `# Tree
## When To Use ## When To Use
Almost anything can be represented in a tree structure. Almost anything can be represented in a tree structure.
Examples include directories, organization hierarchies, biological classifications, countries, etc. The \`Tree\` component is a way of representing the hierarchical relationship between these things. You can also expand, collapse, and select a treeNode within a \`Tree\`. Examples include directories, organization hierarchies, biological classifications, countries, etc. The \`Tree\` component is a way of representing the hierarchical relationship between these things. You can also expand, collapse, and select a treeNode within a \`Tree\`.
## Examples ## Examples
`, `,
@ -41,6 +42,7 @@ export default {
<Dynamic/> <Dynamic/>
<Line/> <Line/>
<Search/> <Search/>
<Directory/>
<api> <api>
<template slot='cn'> <template slot='cn'>
<CN/> <CN/>

14
components/tree/demo/search.md

@ -16,15 +16,15 @@ Searchable Tree.
@expand="onExpand" @expand="onExpand"
:expandedKeys="expandedKeys" :expandedKeys="expandedKeys"
:autoExpandParent="autoExpandParent" :autoExpandParent="autoExpandParent"
:treeNodes="gData" :treeData="gData"
> >
<template slot="title" slot-scope="{key}"> <template slot="title" slot-scope="{title}">
<span v-if="key.indexOf(searchValue) > -1"> <span v-if="title.indexOf(searchValue) > -1">
{{key.substr(0, key.indexOf(searchValue))}} {{title.substr(0, title.indexOf(searchValue))}}
<span style="color: #f50">{{searchValue}}</span> <span style="color: #f50">{{searchValue}}</span>
{{key.substr(key.indexOf(searchValue) + searchValue.length)}} {{title.substr(title.indexOf(searchValue) + searchValue.length)}}
</span> </span>
<span v-else>{{key}}</span> <span v-else>{{title}}</span>
</template> </template>
</a-tree> </a-tree>
</div> </div>
@ -43,7 +43,7 @@ const generateData = (_level, _preKey, _tns) => {
const children = [] const children = []
for (let i = 0; i < x; i++) { for (let i = 0; i < x; i++) {
const key = `${preKey}-${i}` const key = `${preKey}-${i}`
tns.push({ key, scopedSlots: { title: 'title' }}) tns.push({ title: key, key, scopedSlots: { title: 'title' }})
if (i < y) { if (i < y) {
children.push(key) children.push(key)
} }

3
components/tree/index.jsx

@ -1,9 +1,6 @@
import Tree from './Tree' import Tree from './Tree'
import DirectoryTree from './DirectoryTree' import DirectoryTree from './DirectoryTree'
// export {
// TreeProps,
// } from './Tree'
Tree.TreeNode.name = 'ATreeNode' Tree.TreeNode.name = 'ATreeNode'
Tree.DirectoryTree = DirectoryTree Tree.DirectoryTree = DirectoryTree

183
components/tree/index.old.jsx

@ -1,183 +0,0 @@
import VcTree, { TreeNode } from '../vc-tree'
import animation from '../_util/openAnimation'
import PropTypes from '../_util/vue-types'
import { initDefaultProps, getOptionProps } from '../_util/props-util'
// export interface AntTreeNodeProps {
// disabled: PropTypes.bool,
// disableCheckbox: PropTypes.bool,
// title?: string | React.ReactNode;
// key?: string;
// isLeaf: PropTypes.bool,
// children?: React.ReactNode;
// }
// export interface AntTreeNode extends React.Component<AntTreeNodeProps, {}> {}
// export interface AntTreeNodeEvent {
// event: 'check' | 'select';
// node: AntTreeNode;
// checked: PropTypes.bool,
// checkedNodes?: Array<AntTreeNode>;
// selected: PropTypes.bool,
// selectedNodes?: Array<AntTreeNode>;
// }
// export interface AntTreeNodeMouseEvent {
// node: AntTreeNode;
// event: React.MouseEventHandler<any>;
// }
export const TreeProps = () => ({
treeNodes: PropTypes.array,
showLine: PropTypes.bool,
/** 是否支持多选 */
multiple: PropTypes.boolean,
/** 是否自动展开父节点 */
autoExpandParent: PropTypes.boolean,
/** checkable状态下节点选择完全受控(父子节点选中状态不再关联)*/
checkStrictly: PropTypes.bool,
/** 是否支持选中 */
checkable: PropTypes.bool,
/** 默认展开所有树节点 */
defaultExpandAll: PropTypes.bool,
/** 默认展开指定的树节点 */
defaultExpandedKeys: PropTypes.arrayOf(PropTypes.string),
/** (受控)展开指定的树节点 */
expandedKeys: PropTypes.arrayOf(PropTypes.string),
/** (受控)选中复选框的树节点 */
checkedKeys: PropTypes.oneOfType(
[
PropTypes.arrayOf(PropTypes.string),
PropTypes.shape({
checked: PropTypes.arrayOf(String),
halfChecked: PropTypes.arrayOf(String),
}).loose,
]
),
/** 默认选中复选框的树节点 */
defaultCheckedKeys: PropTypes.arrayOf(PropTypes.string),
/** (受控)设置选中的树节点 */
selectedKeys: PropTypes.arrayOf(PropTypes.string),
/** 默认选中的树节点 */
defaultSelectedKeys: PropTypes.arrayOf(PropTypes.string),
/** 展开/收起节点时触发 */
// onExpand?: (expandedKeys: Array<string>, info: { node: AntTreeNode, expanded: boolean }) => void | PromiseLike<any>;
/** 点击复选框触发 */
// onCheck?: (checkedKeys: Array<string>, e: AntTreeNodeEvent) => void;
/** 点击树节点触发 */
// onSelect?: (selectedKeys: Array<string>, e: AntTreeNodeEvent) => void;
/** filter some AntTreeNodes as you need. it should return true */
filterAntTreeNode: PropTypes.func,
/** 异步加载数据 */
loadData: PropTypes.func,
/** 响应右键点击 */
// onRightClick?: (options: AntTreeNodeMouseEvent) => void;
/** 设置节点可拖拽(IE>8)*/
draggable: PropTypes.bool,
// /** */
// onDragStart?: (options: AntTreeNodeMouseEvent) => void;
// /** dragenter */
// onDragEnter?: (options: AntTreeNodeMouseEvent) => void;
// /** dragover */
// onDragOver?: (options: AntTreeNodeMouseEvent) => void;
// /** dragleave */
// onDragLeave?: (options: AntTreeNodeMouseEvent) => void;
// /** drop */
// onDrop?: (options: AntTreeNodeMouseEvent) => void;
prefixCls: PropTypes.string,
filterTreeNode: PropTypes.func,
showIcon: PropTypes.bool,
openAnimation: PropTypes.any,
})
const Tree = {
name: 'ATree',
TreeNode: { ...TreeNode, name: 'ATreeNode' },
props: initDefaultProps(TreeProps(), {
prefixCls: 'ant-tree',
checkable: false,
showIcon: false,
openAnimation: animation,
}),
model: {
prop: 'checkedKeys',
event: 'check',
},
methods: {
handleCheck (checkedKeys, e) {
this.$emit('check', checkedKeys, e)
},
handelSelect (selectedKeys, e) {
this.$emit('select', selectedKeys, e)
this.$emit('update:select', selectedKeys)
},
handleExpand (expandedKeys, info) {
this.$emit('expand', expandedKeys, info)
this.$emit('update:expand', expandedKeys)
},
renderTreeNodes (data = []) {
const { $slots, $scopedSlots } = this
return data.map((item) => {
const { children, on = {}, slots = {}, scopedSlots = {}, key, class: cls, style, ...restProps } = item
const treeNodeProps = {
props: {
...restProps,
icon: restProps.icon ||
$slots[slots.icon] ||
($scopedSlots[scopedSlots.icon] && $scopedSlots[scopedSlots.icon]),
title: restProps.title ||
$slots[slots.title] ||
($scopedSlots[scopedSlots.title] && $scopedSlots[scopedSlots.title])(item),
dataRef: item,
},
on,
key,
class: cls,
style,
}
if (children) {
return (
<TreeNode {...treeNodeProps}>
{this.renderTreeNodes(children)}
</TreeNode>
)
}
return <TreeNode {...treeNodeProps} />
})
},
},
render () {
const props = getOptionProps(this)
const { prefixCls, checkable, treeNodes, ...restProps } = props
const { handelSelect, handleCheck, handleExpand, renderTreeNodes } = this
const vcTreeProps = {
props: {
...restProps,
prefixCls,
checkable: checkable ? <span class={`${prefixCls}-checkbox-inner`} /> : checkable,
},
on: {
...this.$listeners,
check: handleCheck,
select: handelSelect,
expand: handleExpand,
},
}
return (
<VcTree {...vcTreeProps}>
{treeNodes ? renderTreeNodes(treeNodes) : this.$slots.default}
</VcTree>
)
},
}
/* istanbul ignore next */
Tree.install = function (Vue) {
Vue.component(Tree.name, Tree)
Vue.component(Tree.TreeNode.name, Tree.TreeNode)
}
export default Tree

4
components/tree/util.js

@ -1,4 +1,5 @@
import { getNodeChildren, convertTreeToEntities } from '../vc-tree/src/util' import { getNodeChildren, convertTreeToEntities } from '../vc-tree/src/util'
import { getSlots } from '../_util/props-util'
const Record = { const Record = {
None: 'node', None: 'node',
@ -11,7 +12,8 @@ function traverseNodesKey (rootChildren, callback) {
const nodeList = getNodeChildren(rootChildren) || [] const nodeList = getNodeChildren(rootChildren) || []
function processNode (node) { function processNode (node) {
const { key, props: { children }} = node const { key } = node
const children = getSlots(node).default
if (callback(key) !== false) { if (callback(key) !== false) {
traverseNodesKey(children, callback) traverseNodesKey(children, callback)
} }

8
components/vc-tree/src/Tree.jsx

@ -382,7 +382,7 @@ const Tree = {
selected: targetSelected, selected: targetSelected,
node: treeNode, node: treeNode,
selectedNodes, selectedNodes,
nativeEvent: e.nativeEvent, nativeEvent: e,
} }
this.__emit('select', selectedKeys, eventObj) this.__emit('select', selectedKeys, eventObj)
}, },
@ -397,7 +397,7 @@ const Tree = {
event: 'check', event: 'check',
node: treeNode, node: treeNode,
checked, checked,
nativeEvent: e.nativeEvent, nativeEvent: e,
} }
if (checkStrictly) { if (checkStrictly) {
@ -500,7 +500,7 @@ const Tree = {
this.__emit('expand', expandedKeys, { this.__emit('expand', expandedKeys, {
node: treeNode, node: treeNode,
expanded: targetExpanded, expanded: targetExpanded,
nativeEvent: e.nativeEvent, nativeEvent: e,
}) })
// Async Load data // Async Load data
@ -608,7 +608,7 @@ const Tree = {
class={classNames(prefixCls, { class={classNames(prefixCls, {
[`${prefixCls}-show-line`]: showLine, [`${prefixCls}-show-line`]: showLine,
})} })}
role='tree-node' role='tree'
unselectable='on' unselectable='on'
tabIndex={focusable ? tabIndex : null} tabIndex={focusable ? tabIndex : null}
onKeydown={focusable ? this.onKeydown : () => {}} onKeydown={focusable ? this.onKeydown : () => {}}

17
components/vc-tree/src/TreeNode.jsx

@ -258,10 +258,10 @@ const TreeNode = {
// Load data to avoid default expanded tree without data // Load data to avoid default expanded tree without data
syncLoadData (props) { syncLoadData (props) {
const { expanded, loading, loaded } = props const { expanded, loading, loaded } = props
const { vcTree: { onNodeLoad }} = this const { vcTree: { loadData, onNodeLoad }} = this
if (loading) return if (loading) return
// read from state to avoid loadData at same time // read from state to avoid loadData at same time
if (expanded && !this.isLeaf2()) { if (loadData && expanded && !this.isLeaf2()) {
// We needn't reload data when has children in sync logic // We needn't reload data when has children in sync logic
// It's only needed in node expanded // It's only needed in node expanded
const hasChildren = this.getNodeChildren().length !== 0 const hasChildren = this.getNodeChildren().length !== 0
@ -338,12 +338,11 @@ const TreeNode = {
}, },
// Icon + Title // Icon + Title
renderSelector () { renderSelector (h) {
const { selected, icon, loading, dragNodeHighlight, $scopedSlots } = this const { selected, icon, loading, dragNodeHighlight } = this
const { vcTree: { prefixCls, showIcon, draggable, loadData }} = this const { vcTree: { prefixCls, showIcon, icon: treeIcon, draggable, loadData }} = this
const disabled = this.isDisabled() const disabled = this.isDisabled()
const title = getComponentFromProp(this, 'title') || defaultTitle const title = getComponentFromProp(this, 'title') || defaultTitle
const treeIcon = getComponentFromProp(this, 'icon') || $scopedSlots.icon
const wrapClass = `${prefixCls}-node-content-wrapper` const wrapClass = `${prefixCls}-node-content-wrapper`
// Icon - Still show loading icon when loading without showIcon // Icon - Still show loading icon when loading without showIcon
@ -359,7 +358,7 @@ const TreeNode = {
)} )}
> >
{typeof currentIcon === 'function' {typeof currentIcon === 'function'
? currentIcon({ ...this.$props }) : currentIcon} ? currentIcon(h, { ...this.$props }) : currentIcon}
</span> </span>
) : this.renderIcon() ) : this.renderIcon()
} else if (loadData && loading) { } else if (loadData && loading) {
@ -446,7 +445,7 @@ const TreeNode = {
}, },
}, },
render () { render (h) {
const { const {
dragOver, dragOverGapTop, dragOverGapBottom, dragOver, dragOverGapTop, dragOverGapBottom,
isLeaf, isLeaf,
@ -481,7 +480,7 @@ const TreeNode = {
> >
{this.renderSwitcher()} {this.renderSwitcher()}
{this.renderCheckbox()} {this.renderCheckbox()}
{this.renderSelector()} {this.renderSelector(h)}
{this.renderChildren()} {this.renderChildren()}
</li> </li>
) )

378
components/vc-tree/src/util.1.js

@ -1,378 +0,0 @@
/* eslint no-loop-func: 0*/
import warning from 'warning'
import { getSlotOptions, getOptionProps } from '../../_util/props-util'
const DRAG_SIDE_RANGE = 0.25
const DRAG_MIN_GAP = 2
let onlyTreeNodeWarned = false
export function warnOnlyTreeNode () {
if (onlyTreeNodeWarned) return
onlyTreeNodeWarned = true
warning(false, 'Tree only accept TreeNode as children.')
}
export function arrDel (list, value) {
const clone = list.slice()
const index = clone.indexOf(value)
if (index >= 0) {
clone.splice(index, 1)
}
return clone
}
export function arrAdd (list, value) {
const clone = list.slice()
if (clone.indexOf(value) === -1) {
clone.push(value)
}
return clone
}
export function posToArr (pos) {
return pos.split('-')
}
export function getPosition (level, index) {
return `${level}-${index}`
}
export function isTreeNode (node) {
return getSlotOptions(node).isTreeNode
}
export function getNodeChildren (children = []) {
return children.filter(isTreeNode)
}
export function isCheckDisabled (node) {
const { disabled, disableCheckbox } = getOptionProps(node) || {}
return !!(disabled || disableCheckbox)
}
export function traverseTreeNodes (treeNodes, subTreeData, callback) {
function processNode (node, index, parent) {
const children = node ? node.componentOptions.children : treeNodes
const pos = node ? getPosition(parent.pos, index) : 0
// Filter children
const childList = getNodeChildren(children)
// Process node if is not root
if (node) {
const data = {
node,
index,
pos,
key: node.key || pos,
parentPos: parent.node ? parent.pos : null,
}
callback(data)
}
// Process children node
childList.forEach((subNode, subIndex) => {
processNode(subNode, subIndex, { node, pos })
})
}
processNode(null)
}
/**
* Use `rc-util` `toArray` to get the children list which keeps the key.
* And return single node if children is only one(This can avoid `key` missing check).
*/
export function mapChildren (children = [], func) {
const list = children.map(func)
if (list.length === 1) {
return list[0]
}
return list
}
/**
* [Legacy] Return halfChecked when it has value.
* @param checkedKeys
* @param halfChecked
* @returns {*}
*/
export function getStrictlyValue (checkedKeys, halfChecked) {
if (halfChecked) {
return { checked: checkedKeys, halfChecked }
}
return checkedKeys
}
export function getFullKeyList (treeNodes) {
const keyList = []
traverseTreeNodes(treeNodes, ({ key }) => {
keyList.push(key)
})
return keyList
}
/**
* Check position relation.
* @param parentPos
* @param childPos
* @param directly only directly parent can be true
* @returns {boolean}
*/
export function isParent (parentPos, childPos, directly = false) {
if (!parentPos || !childPos || parentPos.length > childPos.length) return false
const parentPath = posToArr(parentPos)
const childPath = posToArr(childPos)
// Directly check
if (directly && parentPath.length !== childPath.length - 1) return false
const len = parentPath.length
for (let i = 0; i < len; i += 1) {
if (parentPath[i] !== childPath[i]) return false
}
return true
}
/**
* Statistic TreeNodes info
* @param treeNodes
* @returns {{}}
*/
export function getNodesStatistic (treeNodes) {
const statistic = {
keyNodes: {},
posNodes: {},
nodeList: [],
}
traverseTreeNodes(treeNodes, true, ({ node, index, pos, key, subNodes, parentPos }) => {
const data = { node, index, pos, key, subNodes, parentPos }
statistic.keyNodes[key] = data
statistic.posNodes[pos] = data
statistic.nodeList.push(data)
})
return statistic
}
export function getDragNodesKeys (treeNodes, node) {
const { eventKey, pos } = getOptionProps(node)
const dragNodesKeys = []
traverseTreeNodes(treeNodes, ({ pos: nodePos, key }) => {
if (isParent(pos, nodePos)) {
dragNodesKeys.push(key)
}
})
dragNodesKeys.push(eventKey || pos)
return dragNodesKeys
}
export function calcDropPosition (event, treeNode) {
const { clientY } = event
const { top, bottom, height } = treeNode.$refs.selectHandle.getBoundingClientRect()
const des = Math.max(height * DRAG_SIDE_RANGE, DRAG_MIN_GAP)
if (clientY <= top + des) {
return -1
} else if (clientY >= bottom - des) {
return 1
}
return 0
}
/**
* Auto expand all related node when sub node is expanded
* @param keyList
* @param props
* @returns [string]
*/
export function calcExpandedKeys (keyList, props, children = []) {
if (!keyList) {
return []
}
// Fill parent expanded keys
const { keyNodes, nodeList } = getNodesStatistic(children)
const needExpandKeys = {}
const needExpandPathList = []
// Fill expanded nodes
keyList.forEach((key) => {
const node = keyNodes[key]
if (node) {
needExpandKeys[key] = true
needExpandPathList.push(node.pos)
}
})
// Match parent by path
nodeList.forEach(({ pos, key }) => {
if (needExpandPathList.some(childPos => isParent(pos, childPos))) {
needExpandKeys[key] = true
}
})
const calcExpandedKeyList = Object.keys(needExpandKeys)
// [Legacy] Return origin keyList if calc list is empty
return calcExpandedKeyList.length ? calcExpandedKeyList : keyList
}
/**
* Return selectedKeys according with multiple prop
* @param selectedKeys
* @param props
* @returns [string]
*/
export function calcSelectedKeys (selectedKeys, props) {
if (!selectedKeys) {
return undefined
}
const { multiple } = props
if (multiple) {
return selectedKeys.slice()
}
if (selectedKeys.length) {
return [selectedKeys[0]]
}
return selectedKeys
}
/**
* Check conduct is by key level. It pass though up & down.
* When conduct target node is check means already conducted will be skip.
* @param treeNodes
* @param checkedKeys
* @returns {{checkedKeys: Array, halfCheckedKeys: Array}}
*/
export function calcCheckStateConduct (treeNodes, checkedKeys) {
const { keyNodes, posNodes } = getNodesStatistic(treeNodes)
const tgtCheckedKeys = {}
const tgtHalfCheckedKeys = {}
// Conduct up
function conductUp (key, halfChecked) {
if (tgtCheckedKeys[key]) return
const { subNodes = [], parentPos, node } = keyNodes[key]
if (isCheckDisabled(node)) return
const allSubChecked = !halfChecked && subNodes
.filter(sub => !isCheckDisabled(sub.node))
.every(sub => tgtCheckedKeys[sub.key])
if (allSubChecked) {
tgtCheckedKeys[key] = true
} else {
tgtHalfCheckedKeys[key] = true
}
if (parentPos !== null) {
conductUp(posNodes[parentPos].key, !allSubChecked)
}
}
// Conduct down
function conductDown (key) {
if (tgtCheckedKeys[key]) return
const { subNodes = [], node } = keyNodes[key]
if (isCheckDisabled(node)) return
tgtCheckedKeys[key] = true
subNodes.forEach((sub) => {
conductDown(sub.key)
})
}
function conduct (key) {
if (!keyNodes[key]) {
warning(false, `'${key}' does not exist in the tree.`)
return
}
const { subNodes = [], parentPos, node } = keyNodes[key]
tgtCheckedKeys[key] = true
if (isCheckDisabled(node)) return
// Conduct down
subNodes
.filter(sub => !isCheckDisabled(sub.node))
.forEach((sub) => {
conductDown(sub.key)
})
// Conduct up
if (parentPos !== null) {
conductUp(posNodes[parentPos].key)
}
}
checkedKeys.forEach((key) => {
conduct(key)
})
return {
checkedKeys: Object.keys(tgtCheckedKeys),
halfCheckedKeys: Object.keys(tgtHalfCheckedKeys)
.filter(key => !tgtCheckedKeys[key]),
}
}
function keyListToString (keyList) {
if (!keyList) return keyList
return keyList.map(key => String(key))
}
/**
* Calculate the value of checked and halfChecked keys.
* This should be only run in init or props changed.
*/
export function calcCheckedKeys (keys, props, children = []) {
const { checkable, checkStrictly } = props
if (!checkable || !keys) {
return null
}
// Convert keys to object format
let keyProps
if (Array.isArray(keys)) {
// [Legacy] Follow the api doc
keyProps = {
checkedKeys: keys,
halfCheckedKeys: undefined,
}
} else if (typeof keys === 'object') {
keyProps = {
checkedKeys: keys.checked || undefined,
halfCheckedKeys: keys.halfChecked || undefined,
}
} else {
warning(false, '`CheckedKeys` is not an array or an object')
return null
}
keyProps.checkedKeys = keyListToString(keyProps.checkedKeys)
keyProps.halfCheckedKeys = keyListToString(keyProps.halfCheckedKeys)
// Do nothing if is checkStrictly mode
if (checkStrictly) {
return keyProps
}
// Conduct calculate the check status
const { checkedKeys = [] } = keyProps
return calcCheckStateConduct(children, checkedKeys)
}
Loading…
Cancel
Save