This commit is contained in:
tangjinzhou 2018-04-13 18:58:58 +08:00
parent 8eb563435b
commit c7e83d6142
20 changed files with 1008 additions and 66 deletions

View File

@ -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'

View File

@ -40,3 +40,4 @@ import './progress/style'
import './timeline/style'
import './input-number/style'
import './transfer/style'
import './tree/style'

View File

@ -0,0 +1,93 @@
<cn>
#### 受控操作示例
受控操作示例
</cn>
<us>
#### basic controlled example
basic controlled example
</us>
```html
<template>
<a-tree
checkable
@expand="onExpand"
:expandedKeys="expandedKeys"
:autoExpandParent="autoExpandParent"
@check="onCheck"
:checkedKeys="checkedKeys"
@select="onSelect"
:selectedKeys="selectedKeys"
:data="treeData"
/>
</template>
<script>
const treeData = [{
title: '0-0',
key: '0-0',
children: [{
title: '0-0-0',
key: '0-0-0',
children: [
{ title: '0-0-0-0', key: '0-0-0-0' },
{ title: '0-0-0-1', key: '0-0-0-1' },
{ title: '0-0-0-2', key: '0-0-0-2' },
],
}, {
title: '0-0-1',
key: '0-0-1',
children: [
{ title: '0-0-1-0', key: '0-0-1-0' },
{ title: '0-0-1-1', key: '0-0-1-1' },
{ title: '0-0-1-2', key: '0-0-1-2' },
],
}, {
title: '0-0-2',
key: '0-0-2',
}],
}, {
title: '0-1',
key: '0-1',
children: [
{ title: '0-1-0-0', key: '0-1-0-0' },
{ title: '0-1-0-1', key: '0-1-0-1' },
{ title: '0-1-0-2', key: '0-1-0-2' },
],
}, {
title: '0-2',
key: '0-2',
}]
export default {
data () {
return {
expandedKeys: ['0-0-0', '0-0-1'],
autoExpandParent: true,
checkedKeys: ['0-0-0'],
selectedKeys: [],
treeData,
}
},
methods: {
onExpand (expandedKeys) {
console.log('onExpand', arguments)
// if not set autoExpandParent to false, if children expanded, parent can not collapse.
// or, you can remove all expanded children keys.
this.expandedKeys = expandedKeys
this.autoExpandParent = false
},
onCheck (checkedKeys) {
console.log('onCheck', checkedKeys)
this.checkedKeys = checkedKeys
},
onSelect (selectedKeys, info) {
console.log('onSelect', info)
this.selectedKeys = selectedKeys
},
},
}
</script>
```

View File

@ -0,0 +1,64 @@
<cn>
#### 基本用法
最简单的用法,展示可勾选,可选中,禁用,默认展开等功能。
</cn>
<us>
#### Basic
The most basic usage, tell you how to use checkable, selectable, disabled, defaultExpandKeys, and etc.
</us>
```html
<template>
<a-tree
checkable
:data="treeData"
:defaultExpandedKeys="['0-0-0', '0-0-1']"
:defaultSelectedKeys="['0-0-0', '0-0-1']"
:defaultCheckedKeys="['0-0-0', '0-0-1']"
@select="this.onSelect"
@check="this.onCheck"
>
<span slot="title0010" style="color: #1890ff">sss</span>
</a-tree>
</template>
<script>
const treeData = [{
title: 'parent 1',
key: '0-0',
children: [{
title: 'parent 1-0',
key: '0-0-0',
disabled: true,
children: [
{ title: 'leaf', key: '0-0-0-0', disableCheckbox: true },
{ title: 'leaf', key: '0-0-0-1' },
],
}, {
title: 'parent 1-1',
key: '0-0-1',
children: [
{ key: '0-0-1-0', slots: { title: 'title0010' }},
],
}],
}]
export default {
data () {
return {
treeData,
}
},
methods: {
onSelect (selectedKeys, info) {
console.log('selected', selectedKeys, info)
},
onCheck (checkedKeys, info) {
console.log('onCheck', checkedKeys, info)
},
},
}
</script>
```

View File

@ -0,0 +1,56 @@
<cn>
#### 自定义图标
可以针对不同的节点定制图标。
</cn>
<us>
#### Customize Icon
You can customize icons for different nodes.
</us>
```html
<template>
<a-tree
:data="treeData"
showIcon
defaultExpandAll
:defaultSelectedKeys="['0-0-0']"
>
<a-icon slot="smile" type="smile-o" />
<a-icon slot="meh" type="smile-o" />
<template slot="custom" slot-scope="{selected}">
<a-icon :type="selected ? 'frown':'frown-o'" />
</template>
</a-tree>
</template>
<script>
const treeData = [{
title: 'parent 1',
key: '0-0',
slots: {
icon: 'smile',
},
children: [
{ title: 'leaf', key: '0-0-0', slots: { icon: 'meh' }},
{ title: 'leaf', key: '0-1-1', scopedSlots: { icon: 'custom' }}],
}]
export default {
data () {
return {
treeData,
}
},
methods: {
onSelect (selectedKeys, info) {
console.log('selected', selectedKeys, info)
},
onCheck (checkedKeys, info) {
console.log('onCheck', checkedKeys, info)
},
},
}
</script>
```

View File

@ -0,0 +1,112 @@
<cn>
#### 拖动示例
将节点拖拽到其他节点内部或前后。
</cn>
<us>
#### draggable
Drag treeNode to insert after the other treeNode or insert into the other parent TreeNode.
</us>
```html
<template>
<a-tree
class="draggable-tree"
:defaultExpandedKeys="expandedKeys"
draggable
@dragenter="onDragEnter"
@drop="onDrop"
:data="gData"
/>
</template>
<script>
const x = 3
const y = 2
const z = 1
const gData = []
const generateData = (_level, _preKey, _tns) => {
const preKey = _preKey || '0'
const tns = _tns || gData
const children = []
for (let i = 0; i < x; i++) {
const key = `${preKey}-${i}`
tns.push({ title: key, key })
if (i < y) {
children.push(key)
}
}
if (_level < 0) {
return tns
}
const level = _level - 1
children.forEach((key, index) => {
tns[index].children = []
return generateData(level, key, tns[index].children)
})
}
generateData(z)
export default {
data () {
return {
gData,
expandedKeys: ['0-0', '0-0-0', '0-0-0-0'],
}
},
methods: {
onDragEnter (info) {
console.log(info)
// expandedKeys 需要受控时设置
// this.expandedKeys = info.expandedKeys
},
onDrop (info) {
console.log(info)
const dropKey = info.node.eventKey
const dragKey = info.dragNode.eventKey
const dropPos = info.node.pos.split('-')
const dropPosition = info.dropPosition - Number(dropPos[dropPos.length - 1])
// const dragNodesKeys = info.dragNodesKeys;
const loop = (data, key, callback) => {
data.forEach((item, index, arr) => {
if (item.key === key) {
return callback(item, index, arr)
}
if (item.children) {
return loop(item.children, key, callback)
}
})
}
const data = [...this.gData]
let dragObj
loop(data, dragKey, (item, index, arr) => {
arr.splice(index, 1)
dragObj = item
})
if (info.dropToGap) {
let ar
let i
loop(data, dropKey, (item, index, arr) => {
ar = arr
i = index
})
if (dropPosition === -1) {
ar.splice(i, 0, dragObj)
} else {
ar.splice(i + 1, 0, dragObj)
}
} else {
loop(data, dropKey, (item) => {
item.children = item.children || []
// where to insert 示例添加到尾部,可以是随意位置
item.children.push(dragObj)
})
}
this.gData = data
},
},
}
</script>
```

View File

@ -0,0 +1,18 @@
<cn>
#### 异步数据加载
点击展开节点,动态加载数据。
</cn>
<us>
#### load data asynchronously
To load data asynchronously when click to expand a treeNode.
</us>
```html
<template>
</template>
<script>
</script>
```

View File

@ -0,0 +1,46 @@
<cn>
#### 连接线
带连接线的树。
</cn>
<us>
#### Tree With Line
Tree With Line
</us>
```html
<template>
<a-tree
showLine
:defaultExpandedKeys="['0-0-0']"
@select="onSelect"
>
<a-tree-node key="0-0">
<span slot="title" style="color: #1890ff">parent 1</span>
<a-tree-node title="parent 1-0" key="0-0-0">
<a-tree-node title="leaf" key="0-0-0-0" />
<a-tree-node title="leaf" key="0-0-0-1" />
<a-tree-node title="leaf" key="0-0-0-2" />
</a-tree-node>
<a-tree-node title="parent 1-1" key="0-0-1">
<a-tree-node title="leaf" key="0-0-1-0" />
</a-tree-node>
<a-tree-node title="parent 1-2" key="0-0-2">
<a-tree-node title="leaf" key="0-0-2-0" />
<a-tree-node title="leaf" key="0-0-2-1" />
</a-tree-node>
</a-tree-node>
</a-tree>
</template>
<script>
export default {
methods: {
onSelect (selectedKeys, info) {
console.log('selected', selectedKeys, info)
},
},
}
</script>
```

View File

@ -0,0 +1,18 @@
<cn>
#### 可搜索
可搜索的树。
</cn>
<us>
#### Searchable
Searchable Tree.
</us>
```html
<template>
</template>
<script>
</script>
```

View File

@ -0,0 +1,39 @@
<template>
<a-tree
:loadData="onLoadData"
:data="treeData"
/>
</template>
<script>
export default {
data () {
return {
treeData: [
{ title: 'Expand to load', key: '0' },
{ title: 'Expand to load', key: '1' },
{ title: 'Tree Node', key: '2', isLeaf: true },
],
}
},
methods: {
onLoadData (treeNode) {
console.log(treeNode.dataRef)
return new Promise((resolve) => {
if (treeNode.dataRef.children) {
resolve()
return
}
setTimeout(() => {
treeNode.dataRef.children = [
{ title: 'Child Node', key: `${treeNode.eventKey}-0` },
{ title: 'Child Node', key: `${treeNode.eventKey}-1` },
]
this.treeData = [...this.treeData]
resolve()
}, 1000)
})
},
},
}
</script>

View File

@ -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
? <Tree>{this.state.treeData.map(data => <TreeNode />)}</Tree>
: 'loading tree'}
```

173
components/tree/index.jsx Normal file
View File

@ -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<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 = () => ({
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<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,
})
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 (
<TreeNode {...treeNodeProps}>
{this.renderTreeNodes(children)}
</TreeNode>
)
}
return <TreeNode {...treeNodeProps} />
})
},
},
render () {
const props = getOptionProps(this)
const { prefixCls, checkable, data, ...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}>
{data ? renderTreeNodes(data) : this.$slots.default}
</VcTree>
)
},
}

View File

@ -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
? <Tree>{this.state.treeData.map(data => <TreeNode />)}</Tree>
: 'loading tree'}
```

View File

@ -0,0 +1,5 @@
import '../../style/index.less'
import './index.less'
// style dependencies
import '../../checkbox/style'

View File

@ -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;
}
}
}

View File

@ -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;
}
}

View File

@ -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,

View File

@ -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}
</span>
) : this.renderIcon()
} else if (loadData && loadStatus === LOAD_STATUS_LOADING) {

View File

@ -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)

View File

@ -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}`),
}
}