diff --git a/components/index.js b/components/index.js index 145b1ab51..04dedc6e7 100644 --- a/components/index.js +++ b/components/index.js @@ -100,7 +100,7 @@ export { default as Table } from './table' export { default as Transfer } from './transfer' -// export { default as Tree } from './tree' +export { default as Tree } from './tree' // export { default as TreeSelect } from './tree-select' diff --git a/components/style.js b/components/style.js index 8f24af65c..f76808c86 100644 --- a/components/style.js +++ b/components/style.js @@ -40,3 +40,4 @@ import './progress/style' import './timeline/style' import './input-number/style' import './transfer/style' +import './tree/style' diff --git a/components/tree/demo/basic-controlled.md b/components/tree/demo/basic-controlled.md new file mode 100644 index 000000000..3deb7a9f6 --- /dev/null +++ b/components/tree/demo/basic-controlled.md @@ -0,0 +1,93 @@ + +#### 受控操作示例 +受控操作示例 + + + +#### basic controlled example +basic controlled example + + +```html + + + +``` diff --git a/components/tree/demo/basic.md b/components/tree/demo/basic.md new file mode 100644 index 000000000..e5751a9af --- /dev/null +++ b/components/tree/demo/basic.md @@ -0,0 +1,64 @@ + +#### 基本用法 +最简单的用法,展示可勾选,可选中,禁用,默认展开等功能。 + + + +#### Basic +The most basic usage, tell you how to use checkable, selectable, disabled, defaultExpandKeys, and etc. + + +```html + + + +``` diff --git a/components/tree/demo/customized-icon.md b/components/tree/demo/customized-icon.md new file mode 100644 index 000000000..e465eb193 --- /dev/null +++ b/components/tree/demo/customized-icon.md @@ -0,0 +1,56 @@ + +#### 自定义图标 +可以针对不同的节点定制图标。 + + + +#### Customize Icon +You can customize icons for different nodes. + + +```html + + + +``` diff --git a/components/tree/demo/draggable.md b/components/tree/demo/draggable.md new file mode 100644 index 000000000..3f77f78ac --- /dev/null +++ b/components/tree/demo/draggable.md @@ -0,0 +1,112 @@ + +#### 拖动示例 +将节点拖拽到其他节点内部或前后。 + + + +#### draggable +Drag treeNode to insert after the other treeNode or insert into the other parent TreeNode. + + +```html + + + + +``` diff --git a/components/tree/demo/dynamic.md b/components/tree/demo/dynamic.md new file mode 100644 index 000000000..c31f80bb9 --- /dev/null +++ b/components/tree/demo/dynamic.md @@ -0,0 +1,18 @@ + +#### 异步数据加载 +点击展开节点,动态加载数据。 + + + +#### load data asynchronously +To load data asynchronously when click to expand a treeNode. + + +```html + + +``` diff --git a/components/tree/demo/line.md b/components/tree/demo/line.md new file mode 100644 index 000000000..39a381136 --- /dev/null +++ b/components/tree/demo/line.md @@ -0,0 +1,46 @@ + +#### 连接线 +带连接线的树。 + + + +#### Tree With Line +Tree With Line + + +```html + + + + +``` diff --git a/components/tree/demo/search.md b/components/tree/demo/search.md new file mode 100644 index 000000000..cd2ebdf0a --- /dev/null +++ b/components/tree/demo/search.md @@ -0,0 +1,18 @@ + +#### 可搜索 +可搜索的树。 + + + +#### Searchable +Searchable Tree. + + +```html + + +``` diff --git a/components/tree/demo/test.vue b/components/tree/demo/test.vue new file mode 100644 index 000000000..1808be174 --- /dev/null +++ b/components/tree/demo/test.vue @@ -0,0 +1,39 @@ + + + diff --git a/components/tree/index.en-US.md b/components/tree/index.en-US.md new file mode 100644 index 000000000..f9ec8fc28 --- /dev/null +++ b/components/tree/index.en-US.md @@ -0,0 +1,70 @@ +--- +category: Components +type: Data Display +title: Tree +--- + +## When To Use + +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`. + +## API + +### Tree props + +| Property | Description | Type | Default | +| -------- | ----------- | ---- | ------- | +| autoExpandParent | Whether to automatically expand a parent treeNode | boolean | true | +| checkable | Adds a `Checkbox` before the treeNodes | boolean | false | +| checkedKeys | (Controlled) Specifies the keys of the checked treeNodes (PS: When this specifies the key of a treeNode which is also a parent treeNode, all the children treeNodes of will be checked; and vice versa, when it specifies the key of a treeNode which is a child treeNode, its parent treeNode will also be checked. When `checkable` and `checkStrictly` is true, its object has `checked` and `halfChecked` property. Regardless of whether the child or parent treeNode is checked, they won't impact each other. | string\[] \| {checked: string\[], halfChecked: string\[]} | \[] | +| checkStrictly | Check treeNode precisely; parent treeNode and children treeNodes are not associated | boolean | false | +| defaultCheckedKeys | Specifies the keys of the default checked treeNodes | string\[] | \[] | +| defaultExpandAll | Whether to expand all treeNodes by default | boolean | false | +| defaultExpandedKeys | Specify the keys of the default expanded treeNodes | string\[] | \[] | +| defaultExpandParent | auto expand parent treeNodes when init | bool | true | +| defaultSelectedKeys | Specifies the keys of the default selected treeNodes | string\[] | \[] | +| disabled | whether disabled the tree | bool | false | +| draggable | Specifies whether this Tree is draggable (IE > 8) | boolean | false | +| expandedKeys | (Controlled) Specifies the keys of the expanded treeNodes | string\[] | \[] | +| filterTreeNode | Defines a function to filter (highlight) treeNodes. When the function returns `true`, the corresponding treeNode will be highlighted | function(node) | - | +| loadData | Load data asynchronously | function(node) | - | +| multiple | Allows selecting multiple treeNodes | boolean | false | +| selectedKeys | (Controlled) Specifies the keys of the selected treeNodes | string\[] | - | +| showIcon | Shows the icon before a TreeNode's title. There is no default style; you must set a custom style for it if set to `true` | boolean | false | +| showLine | Shows a connecting line | boolean | false | +| onCheck | Callback function for when the onCheck event occurs | function(checkedKeys, e:{checked: bool, checkedNodes, node, event}) | - | +| onDragEnd | Callback function for when the onDragEnd event occurs | function({event, node}) | - | +| onDragEnter | Callback function for when the onDragEnter event occurs | function({event, node, expandedKeys}) | - | +| onDragLeave | Callback function for when the onDragLeave event occurs | function({event, node}) | - | +| onDragOver | Callback function for when the onDragOver event occurs | function({event, node}) | - | +| onDragStart | Callback function for when the onDragStart event occurs | function({event, node}) | - | +| onDrop | Callback function for when the onDrop event occurs | function({event, node, dragNode, dragNodesKeys}) | - | +| onExpand | Callback function for when a treeNode is expanded or collapsed | function(expandedKeys, {expanded: bool, node}) | - | +| onRightClick | Callback function for when the user right clicks a treeNode | function({event, node}) | - | +| onSelect | Callback function for when the user clicks a treeNode | function(selectedKeys, e:{selected: bool, selectedNodes, node, event}) | - | + +### TreeNode props + +| Property | Description | Type | Default | +| -------- | ----------- | ---- | ------- | +| disableCheckbox | Disables the checkbox of the treeNode | boolean | false | +| disabled | Disables the treeNode | boolean | false | +| icon | customize icon. When you pass component, whose render will receive full TreeNode props as component props | element/Function(props):ReactNode | - | +| isLeaf | Determines if this is a leaf node(effective when `loadData` is specified) | boolean | false | +| key | Used with (default)ExpandedKeys / (default)CheckedKeys / (default)SelectedKeys. P.S.: It must be unique in all of treeNodes of the tree! | string | internal calculated position of treeNode | +| selectable | Set whether the treeNode can be selected | boolean | true | +| title | Title | string\|ReactNode | '---' | + +## Note + +Before `3.4.0`: +The number of treeNodes can be very large, but when `checkable=true`, +it will increase the compute time. So, we cache some calculations (e.g. `this.treeNodesStates`) +to avoid double computing. But, this brings some restrictions. +**When you load treeNodes asynchronously, you should render tree like this**: + +```jsx +{this.state.treeData.length + ? {this.state.treeData.map(data => )} + : 'loading tree'} +``` diff --git a/components/tree/index.jsx b/components/tree/index.jsx new file mode 100644 index 000000000..6c16b9ccf --- /dev/null +++ b/components/tree/index.jsx @@ -0,0 +1,173 @@ + +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 {} + +// export interface AntTreeNodeEvent { +// event: 'check' | 'select'; +// node: AntTreeNode; +// checked: PropTypes.bool, +// checkedNodes?: Array; +// selected: PropTypes.bool, +// selectedNodes?: Array; +// } + +// export interface AntTreeNodeMouseEvent { +// node: AntTreeNode; +// event: React.MouseEventHandler; +// } + +export const TreeProps = () => ({ + data: 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, info: { node: AntTreeNode, expanded: boolean }) => void | PromiseLike; + /** 点击复选框触发 */ + // onCheck?: (checkedKeys: Array, e: AntTreeNodeEvent) => void; + /** 点击树节点触发 */ + // onSelect?: (selectedKeys: Array, 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, +}) + +export default { + 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], + dataRef: item, + }, + on, + key, + class: cls, + style, + } + if (children) { + return ( + + {this.renderTreeNodes(children)} + + ) + } + return + }) + }, + }, + + render () { + const props = getOptionProps(this) + const { prefixCls, checkable, data, ...restProps } = props + const { handelSelect, handleCheck, handleExpand, renderTreeNodes } = this + const vcTreeProps = { + props: { + ...restProps, + prefixCls, + checkable: checkable ? : checkable, + }, + on: { + ...this.$listeners, + check: handleCheck, + select: handelSelect, + expand: handleExpand, + }, + } + return ( + + {data ? renderTreeNodes(data) : this.$slots.default} + + ) + }, +} diff --git a/components/tree/index.zh-CN.md b/components/tree/index.zh-CN.md new file mode 100644 index 000000000..7c908a96a --- /dev/null +++ b/components/tree/index.zh-CN.md @@ -0,0 +1,68 @@ +--- +category: Components +type: Data Display +title: Tree +subtitle: 树形控件 +--- + +## 何时使用 + +文件夹、组织架构、生物分类、国家地区等等,世间万物的大多数结构都是树形结构。使用`树控件`可以完整展现其中的层级关系,并具有展开收起选择等交互功能。 + +## API + +### Tree props + +| 参数 | 说明 | 类型 | 默认值 | +| --- | --- | --- | --- | +| autoExpandParent | 是否自动展开父节点 | boolean | true | +| checkable | 节点前添加 Checkbox 复选框 | boolean | false | +| checkedKeys | (受控)选中复选框的树节点(注意:父子节点有关联,如果传入父节点key,则子节点自动选中;相应当子节点key都传入,父节点也自动选中。当设置`checkable`和`checkStrictly`,它是一个有`checked`和`halfChecked`属性的对象,并且父子节点的选中与否不再关联 | string\[] \| {checked: string\[], halfChecked: string\[]} | \[] | +| checkStrictly | checkable状态下节点选择完全受控(父子节点选中状态不再关联) | boolean | false | +| defaultCheckedKeys | 默认选中复选框的树节点 | string\[] | \[] | +| defaultExpandAll | 默认展开所有树节点 | boolean | false | +| defaultExpandedKeys | 默认展开指定的树节点 | string\[] | \[] | +| defaultExpandParent | 默认展开父节点 | bool | true | +| defaultSelectedKeys | 默认选中的树节点 | string\[] | \[] | +| disabled | 将树禁用 | bool | false | +| draggable | 设置节点可拖拽(IE>8) | boolean | false | +| expandedKeys | (受控)展开指定的树节点 | string\[] | \[] | +| filterTreeNode | 按需筛选树节点(高亮),返回true | function(node) | - | +| loadData | 异步加载数据 | function(node) | - | +| multiple | 支持点选多个节点(节点本身) | boolean | false | +| selectedKeys | (受控)设置选中的树节点 | string\[] | - | +| showIcon | 是否展示 TreeNode title 前的图标,没有默认样式,如设置为 true,需要自行定义图标相关样式 | boolean | false | +| showLine | 是否展示连接线 | boolean | false | +| onCheck | 点击复选框触发 | function(checkedKeys, e:{checked: bool, checkedNodes, node, event}) | - | +| onDragEnd | dragend 触发时调用 | function({event, node}) | - | +| onDragEnter | dragenter 触发时调用 | function({event, node, expandedKeys}) | - | +| onDragLeave | dragleave 触发时调用 | function({event, node}) | - | +| onDragOver | dragover 触发时调用 | function({event, node}) | - | +| onDragStart | 开始拖拽时调用 | function({event, node}) | - | +| onDrop | drop 触发时调用 | function({event, node, dragNode, dragNodesKeys}) | - | +| onExpand | 展开/收起节点时触发 | function(expandedKeys, {expanded: bool, node}) | - | +| onRightClick | 响应右键点击 | function({event, node}) | - | +| onSelect | 点击树节点触发 | function(selectedKeys, e:{selected: bool, selectedNodes, node, event}) | - | + +### TreeNode props + +| 参数 | 说明 | 类型 | 默认值 | +| --- | --- | --- | --- | +| disableCheckbox | 禁掉 checkbox | boolean | false | +| disabled | 禁掉响应 | boolean | false | +| icon | 自定义图标。可接收组件,props 为当前节点 props | element/Function(props):ReactNode | - | +| isLeaf | 设置为叶子节点(设置了`loadData`时有效) | boolean | false | +| key | 被树的 (default)ExpandedKeys / (default)CheckedKeys / (default)SelectedKeys 属性所用。注意:整个树范围内的所有节点的 key 值不能重复! | string | 内部计算出的节点位置 | +| selectable | 设置节点是否可被选中 | boolean | true | +| title | 标题 | string\|ReactNode | '---' | + +## 注意 + +在 `3.4.0` 之前: +树节点可以有很多,但在设置`checkable`时,将会花费更多的计算时间,因此我们缓存了一些计算结果(`this.treeNodesStates`)来复用,避免多次重复计算,以此提高性能。但这也带来了一些限制,当你异步加载树节点时,你需要这样渲染树: + +```jsx +{this.state.treeData.length + ? {this.state.treeData.map(data => )} + : 'loading tree'} +``` diff --git a/components/tree/style/index.js b/components/tree/style/index.js new file mode 100644 index 000000000..4c3e27257 --- /dev/null +++ b/components/tree/style/index.js @@ -0,0 +1,5 @@ +import '../../style/index.less' +import './index.less' + +// style dependencies +import '../../checkbox/style' diff --git a/components/tree/style/index.less b/components/tree/style/index.less new file mode 100644 index 000000000..90c3ef888 --- /dev/null +++ b/components/tree/style/index.less @@ -0,0 +1,203 @@ +@import "../../style/themes/default"; +@import "../../style/mixins/index"; +@import "../../checkbox/style/mixin"; +@import "./mixin"; + +@tree-prefix-cls: ~"@{ant-prefix}-tree"; +@tree-showline-icon-color: @text-color-secondary; + +.antCheckboxFn(@checkbox-prefix-cls: ~"@{ant-prefix}-tree-checkbox"); + +.@{tree-prefix-cls} { + .reset-component; + margin: 0; + padding: 0; + + ol, ul { + list-style: none; + margin: 0; + padding: 0; + } + + li { + padding: 4px 0; + margin: 0; + list-style: none; + white-space: nowrap; + outline: 0; + span[draggable], + span[draggable="true"] { + user-select: none; + border-top: 2px transparent solid; + border-bottom: 2px transparent solid; + margin-top: -2px; + /* Required to make elements draggable in old WebKit */ + -khtml-user-drag: element; + -webkit-user-drag: element; + } + &.drag-over { + > span[draggable] { + background-color: @primary-color; + color: white; + opacity: 0.8; + } + } + &.drag-over-gap-top { + > span[draggable] { + border-top-color: @primary-color; + } + } + &.drag-over-gap-bottom { + > span[draggable] { + border-bottom-color: @primary-color; + } + } + &.filter-node { + > span { + color: @highlight-color !important; + font-weight: 500 !important; + } + } + ul { + margin: 0; + padding: 0 0 0 18px; + } + .@{tree-prefix-cls}-node-content-wrapper { + display: inline-block; + padding: 0 5px; + border-radius: @border-radius-sm; + margin: 0; + cursor: pointer; + text-decoration: none; + vertical-align: top; + color: @text-color; + transition: all .3s; + position: relative; + height: 24px; + line-height: 24px; + &:hover { + background-color: @item-hover-bg; + } + &.@{tree-prefix-cls}-node-selected { + background-color: @primary-2; + } + } + span { + &.@{tree-prefix-cls}-checkbox { + margin: 4px 4px 0 2px; + } + &.@{tree-prefix-cls}-switcher, + &.@{tree-prefix-cls}-iconEle { + margin: 0; + width: 24px; + height: 24px; + line-height: 24px; + display: inline-block; + vertical-align: middle; + border: 0 none; + cursor: pointer; + outline: none; + text-align: center; + } + &.@{tree-prefix-cls}-icon_loading { + position: absolute; + left: 0; + top: 1px; + background: #fff; + transform: translateX(-100%); + transition: all .3s; + &:after { + display: inline-block; + .iconfont-font("\E64D"); + animation: loadingCircle 1s infinite linear; + color: @primary-color; + } + } + &.@{tree-prefix-cls}-switcher { + &.@{tree-prefix-cls}-switcher-noop { + cursor: default; + } + &.@{tree-prefix-cls}-switcher_open { + .antTreeSwitcherIcon(); + } + &.@{tree-prefix-cls}-switcher_close { + .antTreeSwitcherIcon(); + &:after { + transform: rotate(270deg) scale(0.59); + } + } + } + } + &:last-child > span { + &.@{tree-prefix-cls}-switcher, + &.@{tree-prefix-cls}-iconEle { + &:before { + display: none; + } + } + } + } + > li { + &:first-child { + padding-top: 7px; + } + &:last-child { + padding-bottom: 7px; + } + } + &-child-tree { + display: none; + &-open { + display: block; + } + } + li&-treenode-disabled { + > span:not(.@{tree-prefix-cls}-switcher), + > .@{tree-prefix-cls}-node-content-wrapper, + > .@{tree-prefix-cls}-node-content-wrapper span { + color: @disabled-color; + cursor: not-allowed; + } + > .@{tree-prefix-cls}-node-content-wrapper:hover { + background: transparent; + } + } + &-icon__open { + margin-right: 2px; + vertical-align: top; + } + &-icon__close { + margin-right: 2px; + vertical-align: top; + } + // Tree with line + &&-show-line { + li { + position: relative; + span { + &.@{tree-prefix-cls}-switcher { + background: @component-background; + color: @tree-showline-icon-color; + &.@{tree-prefix-cls}-switcher-noop { + .antTreeShowLineIcon("tree-doc-icon"); + } + &.@{tree-prefix-cls}-switcher_open { + .antTreeShowLineIcon("tree-showline-open-icon"); + } + &.@{tree-prefix-cls}-switcher_close { + .antTreeShowLineIcon("tree-showline-close-icon"); + } + } + } + } + li:not(:last-child):before { + content: ' '; + width: 1px; + border-left: 1px solid @border-color-base; + height: 100%; + position: absolute; + left: 12px; + margin: 22px 0; + } + } +} diff --git a/components/tree/style/mixin.less b/components/tree/style/mixin.less new file mode 100644 index 000000000..1a4a4cb87 --- /dev/null +++ b/components/tree/style/mixin.less @@ -0,0 +1,27 @@ +@import "../../style/mixins/index"; + +@tree-default-open-icon: "\e606"; +@tree-showline-open-icon: "\e621"; +@tree-showline-close-icon: "\e645"; +@tree-doc-icon: "\e664"; + +.antTreeSwitcherIcon(@type: "tree-default-open-icon") { + &:after { + .iconfont-size-under-12px(7px); + display: inline-block; + .iconfont-font(@@type); + font-weight: bold; + transition: transform .3s; + } +} + +.antTreeShowLineIcon(@type) { + &:after { + .iconfont-size-under-12px(12px); + display: inline-block; + .iconfont-font(@@type); + vertical-align: baseline; + font-weight: normal; + transition: transform .3s; + } +} diff --git a/components/vc-tree/src/Tree.jsx b/components/vc-tree/src/Tree.jsx index 5204380db..7c75378ea 100644 --- a/components/vc-tree/src/Tree.jsx +++ b/components/vc-tree/src/Tree.jsx @@ -16,45 +16,6 @@ import { * Thought we still use `cloneElement` to pass `key`, * other props can pass with context for future refactor. */ -export const contextTypes = { - rcTree: PropTypes.shape({ - root: PropTypes.object, - - prefixCls: PropTypes.string, - selectable: PropTypes.bool, - showIcon: PropTypes.bool, - icon: PropTypes.oneOfType([PropTypes.object, PropTypes.func]), - draggable: PropTypes.bool, - checkable: PropTypes.oneOfType([ - PropTypes.bool, - PropTypes.object, - ]), - checkStrictly: PropTypes.bool, - disabled: PropTypes.bool, - openTransitionName: PropTypes.string, - openAnimation: PropTypes.oneOfType([PropTypes.string, PropTypes.object]), - - loadData: PropTypes.func, - filterTreeNode: PropTypes.func, - renderTreeNode: PropTypes.func, - - isKeyChecked: PropTypes.func, - - // onNodeExpand: PropTypes.func, - // onNodeSelect: PropTypes.func, - // onNodeMouseEnter: PropTypes.func, - // onNodeMouseLeave: PropTypes.func, - // onNodeContextMenu: PropTypes.func, - // onNodeDragStart: PropTypes.func, - // onNodeDragEnter: PropTypes.func, - // onNodeDragOver: PropTypes.func, - // onNodeDragLeave: PropTypes.func, - // onNodeDragEnd: PropTypes.func, - // onNodeDrop: PropTypes.func, - // onBatchNodeCheck: PropTypes.func, - // onCheckConductFinished: PropTypes.func, - }), -} const Tree = { name: 'Tree', @@ -68,10 +29,7 @@ const Tree = { selectable: PropTypes.bool, disabled: PropTypes.bool, multiple: PropTypes.bool, - checkable: PropTypes.oneOfType([ - PropTypes.bool, - PropTypes.node, - ]), + checkable: PropTypes.oneOfType([PropTypes.object, PropTypes.bool]), checkStrictly: PropTypes.bool, draggable: PropTypes.bool, defaultExpandParent: PropTypes.bool, diff --git a/components/vc-tree/src/TreeNode.jsx b/components/vc-tree/src/TreeNode.jsx index 5154308bf..58c4563b5 100644 --- a/components/vc-tree/src/TreeNode.jsx +++ b/components/vc-tree/src/TreeNode.jsx @@ -1,9 +1,8 @@ import PropTypes from '../../_util/vue-types' import classNames from 'classnames' import warning from 'warning' -import { contextTypes } from './Tree' import { getPosition, getNodeChildren, isCheckDisabled, traverseTreeNodes } from './util' -import { initDefaultProps, getOptionProps, filterEmpty } from '../../_util/props-util' +import { initDefaultProps, getOptionProps, filterEmpty, getComponentFromProp } from '../../_util/props-util' import BaseMixin from '../../_util/BaseMixin' import getTransitionProps from '../../_util/getTransitionProps' @@ -19,13 +18,6 @@ const defaultTitle = '---' let onlyTreeNodeWarned = false // Only accept TreeNode -export const nodeContextTypes = { - ...contextTypes, - vcTreeNode: PropTypes.shape({ - onUpCheckConduct: PropTypes.func, - }), -} - const TreeNode = { name: 'TreeNode', mixins: [BaseMixin], @@ -53,9 +45,8 @@ const TreeNode = { disabled: PropTypes.bool, disableCheckbox: PropTypes.bool, icon: PropTypes.any, - }, { - title: defaultTitle, - }), + dataRef: PropTypes.object, + }, {}), data () { return { @@ -358,7 +349,7 @@ const TreeNode = { // read from state to avoid loadData at same time this.setState(({ loadStatus }) => { - if (loadData && loadStatus === LOAD_STATUS_NONE && expanded && !this.isLeaf()) { + if (loadData && loadStatus === LOAD_STATUS_NONE && expanded && !this.isLeaf2()) { loadData(this).then(() => { this.setState({ loadStatus: LOAD_STATUS_LOADED }) }).catch(() => { @@ -449,10 +440,11 @@ const TreeNode = { // Icon + Title renderSelector () { - const { title, selected, icon, loadStatus, dragNodeHighlight } = this - const { vcTree: { prefixCls, showIcon, icon: treeIcon, draggable, loadData }} = this + const { selected, icon, loadStatus, dragNodeHighlight, $scopedSlots } = this + const { vcTree: { prefixCls, showIcon, draggable, loadData }} = this const disabled = this.isDisabled() - + const title = getComponentFromProp(this, 'title') || defaultTitle + const treeIcon = getComponentFromProp(this, 'icon') || $scopedSlots.icon const wrapClass = `${prefixCls}-node-content-wrapper` // Icon - Still show loading icon when loading without showIcon @@ -468,9 +460,7 @@ const TreeNode = { )} > {typeof currentIcon === 'function' - ? currentIcon( - { props: this.$props, on: this.$listeners } - ) : currentIcon} + ? currentIcon(this.$props) : currentIcon} ) : this.renderIcon() } else if (loadData && loadStatus === LOAD_STATUS_LOADING) { diff --git a/site/components.js b/site/components.js index 3bf04be88..9ff10a793 100644 --- a/site/components.js +++ b/site/components.js @@ -44,7 +44,7 @@ import { Switch, Table, Transfer, - // Tree, + Tree, // TreeSelect, Tabs, Tag, @@ -122,7 +122,8 @@ Vue.component(Table.name, Table) Vue.component(Table.Column.name, Table.Column) Vue.component(Table.ColumnGroup.name, Table.ColumnGroup) Vue.component(Transfer.name, Transfer) -// Vue.component(Tree.name, Tree) +Vue.component(Tree.name, Tree) +Vue.component(Tree.TreeNode.name, Tree.TreeNode) // Vue.component(TreeSelect.name, TreeSelect) Vue.component(Tabs.name, Tabs) Vue.component(Tabs.TabPane.name, Tabs.TabPane) diff --git a/site/routes.js b/site/routes.js index 6360a0fc8..e969297dd 100644 --- a/site/routes.js +++ b/site/routes.js @@ -3,7 +3,7 @@ import Layout from './components/layout.vue' const AsyncTestComp = () => { const d = window.location.hash.replace('#', '') return { - component: import(`../components/vc-tree/demo/${d}`), + component: import(`../components/tree/demo/${d}`), } }