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
+
+
+ sss
+
+
+
+
+```
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
+
+
+
+ parent 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+```
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}`),
}
}