tree support accordion

This commit is contained in:
baiyaaaaa 2017-01-14 16:02:52 +08:00 committed by 杨奕
parent 39cbb051f1
commit 2072156e5b
6 changed files with 535 additions and 307 deletions

View File

@ -2,21 +2,36 @@
const data = [{
label: 'Level one 1',
children: [{
label: 'Level two 1-1'
label: 'Level two 1-1',
children: [{
label: 'Level three 1-1-1'
}]
}]
}, {
label: 'Level one 2',
children: [{
label: 'Level two 2-1'
label: 'Level two 2-1',
children: [{
label: 'Level three 2-1-1'
}]
}, {
label: 'Level two 2-2'
label: 'Level two 2-2',
children: [{
label: 'Level three 2-2-1'
}]
}]
}, {
label: 'Level one 3',
children: [{
label: 'Level two 3-1'
label: 'Level two 3-1',
children: [{
label: 'Level three 3-1-1'
}]
}, {
label: 'Level two 3-2'
label: 'Level two 3-2',
children: [{
label: 'Level three 3-2-1'
}]
}]
}];
@ -107,21 +122,36 @@ Basic tree structure.
data: [{
label: 'Level one 1',
children: [{
label: 'Level two 1-1'
label: 'Level two 1-1',
children: [{
label: 'Level three 1-1-1'
}]
}]
}, {
label: 'Level one 2',
children: [{
label: 'Level two 2-1'
label: 'Level two 2-1',
children: [{
label: 'Level three 2-1-1'
}]
}, {
label: 'Level two 2-2'
label: 'Level two 2-2',
children: [{
label: 'Level three 2-2-1'
}]
}]
}, {
label: 'Level one 3',
children: [{
label: 'Level two 3-1'
label: 'Level two 3-1',
children: [{
label: 'Level three 3-1-1'
}]
}, {
label: 'Level two 3-2'
label: 'Level two 3-2',
children: [{
label: 'Level three 3-2-1'
}]
}]
}],
defaultProps: {
@ -214,6 +244,69 @@ Used for node selection. In the following example, data for each layer is acquir
```
:::
### Accordion
Only one node among the same level can be expanded at one time.
::: demo
```html
<el-tree :data="data" :props="defaultProps" @node-click="handleNodeClick"></el-tree>
<script>
export default {
data() {
return {
data: [{
label: 'Level one 1',
children: [{
label: 'Level two 1-1',
children: [{
label: 'Level three 1-1-1'
}]
}]
}, {
label: 'Level one 2',
children: [{
label: 'Level two 2-1',
children: [{
label: 'Level three 2-1-1'
}]
}, {
label: 'Level two 2-2',
children: [{
label: 'Level three 2-2-1'
}]
}]
}, {
label: 'Level one 3',
children: [{
label: 'Level two 3-1',
children: [{
label: 'Level three 3-1-1'
}]
}, {
label: 'Level two 3-2',
children: [{
label: 'Level three 3-2-1'
}]
}]
}],
defaultProps: {
children: 'children',
label: 'label'
}
};
},
methods: {
handleNodeClick(data) {
console.log(data);
}
}
};
</script>
```
:::
### Attributes
| Attribute | Description | Type | Accepted Values | Default |
|---------- |-------------- |---------- |-------------------------------- |-------- |
@ -233,6 +326,7 @@ Used for node selection. In the following example, data for each layer is acquir
| check-strictly | whether checked state of a node not affects its father and child nodes when `show-checkbox` is `true` | boolean | — | false |
| default-checked-keys | array of keys of initially checked nodes | array | — | — |
| filter-node-method | this function will be executed on each node when use filter method. if return `false`, tree node will be hidden. | Function(value, data, node) | — | — |
| accordion | whether only one node among the same level can be expanded at one time | boolean | — | false |
### props
| Attribute | Description | Type | Accepted Values | Default |

View File

@ -14,21 +14,36 @@
const data = [{
label: '一级 1',
children: [{
label: '二级 1-1'
label: '二级 1-1',
children: [{
label: '三级 1-1-1'
}]
}]
}, {
label: '一级 2',
children: [{
label: '二级 2-1'
label: '二级 2-1',
children: [{
label: '三级 2-1-1'
}]
}, {
label: '二级 2-2'
label: '二级 2-2',
children: [{
label: '三级 2-2-1'
}]
}]
}, {
label: '一级 3',
children: [{
label: '二级 3-1'
label: '二级 3-1',
children: [{
label: '三级 3-1-1'
}]
}, {
label: '二级 3-2'
label: '二级 3-2',
children: [{
label: '三级 3-2-1'
}]
}]
}];
@ -119,21 +134,36 @@
data: [{
label: '一级 1',
children: [{
label: '二级 1-1'
label: '二级 1-1',
children: [{
label: '三级 1-1-1'
}]
}]
}, {
label: '一级 2',
children: [{
label: '二级 2-1'
label: '二级 2-1',
children: [{
label: '三级 2-1-1'
}]
}, {
label: '二级 2-2'
label: '二级 2-2',
children: [{
label: '三级 2-2-1'
}]
}]
}, {
label: '一级 3',
children: [{
label: '二级 3-1'
label: '二级 3-1',
children: [{
label: '三级 3-1-1'
}]
}, {
label: '二级 3-2'
label: '二级 3-2',
children: [{
label: '三级 3-2-1'
}]
}]
}],
defaultProps: {
@ -226,6 +256,69 @@
```
:::
### 手风琴模式
每次只打开一个同级树节点展开
::: demo
```html
<el-tree :data="data" :props="defaultProps" @node-click="handleNodeClick"></el-tree>
<script>
export default {
data() {
return {
data: [{
label: '一级 1',
children: [{
label: '二级 1-1',
children: [{
label: '三级 1-1-1'
}]
}]
}, {
label: '一级 2',
children: [{
label: '二级 2-1',
children: [{
label: '三级 2-1-1'
}]
}, {
label: '二级 2-2',
children: [{
label: '三级 2-2-1'
}]
}]
}, {
label: '一级 3',
children: [{
label: '二级 3-1',
children: [{
label: '三级 3-1-1'
}]
}, {
label: '二级 3-2',
children: [{
label: '三级 3-2-1'
}]
}]
}],
defaultProps: {
children: 'children',
label: 'label'
}
};
},
methods: {
handleNodeClick(data) {
console.log(data);
}
}
};
</script>
```
:::
### Attributes
| 参数 | 说明 | 类型 | 可选值 | 默认值 |
|---------- |-------------- |---------- |-------------------------------- |-------- |
@ -245,6 +338,7 @@
| check-strictly | 在显示复选框的情况下,是否严格的遵循父子不互相关联的做法,默认为 false | boolean | — | false |
| default-checked-keys | 默认勾选的节点的 key 的数组 | array | — | — |
| filter-node-method | 对树节点进行筛选时执行的方法,返回 true 表示这个节点可以显示,返回 false 则表示这个节点会被隐藏 | Function(value, data, node) | — | — |
| accordion | 是否每次只打开一个同级树节点展开 | boolean | — | false |
### props
| 参数 | 说明 | 类型 | 可选值 | 默认值 |

View File

@ -35,7 +35,8 @@
:render-content="renderContent"
v-for="child in node.childNodes"
:key="getNodeKey(child)"
:node="child">
:node="child"
@click.native="handleChildNodeClick(child)">
</el-tree-node>
</div>
</collapse-transition>
@ -45,10 +46,15 @@
<script type="text/jsx">
import CollapseTransition from 'element-ui/src/transitions/collapse-transition';
import ElCheckbox from 'element-ui/packages/checkbox';
import emitter from 'element-ui/src/mixins/emitter';
export default {
name: 'ElTreeNode',
componentName: 'ElTreeNode',
mixins: [emitter],
props: {
node: {
default() {
@ -156,6 +162,10 @@
if (!this.node.indeterminate) {
this.node.setChecked(ev.target.checked, !this.tree.checkStrictly);
}
},
handleChildNodeClick(node) {
this.broadcast('ElTreeNode', 'tree-node-click', node);
}
},
@ -186,6 +196,14 @@
this.expanded = true;
this.childNodeRendered = true;
}
if(this.tree.accordion) {
this.$on('tree-node-click', node => {
if(this.node !== node) {
this.node.collapse();
}
});
}
}
};
</script>

View File

@ -5,7 +5,8 @@
:node="child"
:props="props"
:key="getNodeKey(child)"
:render-content="renderContent">
:render-content="renderContent"
@click.native="handleChildNodeClick(child)">
</el-tree-node>
<div class="el-tree__empty-block" v-if="!root.childNodes || root.childNodes.length === 0">
<span class="el-tree__empty-text">{{ emptyText }}</span>
@ -16,10 +17,25 @@
<script type="text/ecmascript-6">
import TreeStore from './model/tree-store';
import {t} from 'element-ui/src/locale';
import emitter from 'element-ui/src/mixins/emitter';
export default {
name: 'ElTree',
mixins: [emitter],
components: {
ElTreeNode: require('./tree-node.vue')
},
data() {
return {
store: null,
root: null,
currentNode: null
};
},
props: {
data: {
type: Array
@ -64,40 +80,8 @@
highlightCurrent: Boolean,
currentNodeKey: [String, Number],
load: Function,
filterNodeMethod: Function
},
created() {
this.isTree = true;
this.store = new TreeStore({
key: this.nodeKey,
data: this.data,
lazy: this.lazy,
props: this.props,
load: this.load,
currentNodeKey: this.currentNodeKey,
checkStrictly: this.checkStrictly,
defaultCheckedKeys: this.defaultCheckedKeys,
defaultExpandedKeys: this.defaultExpandedKeys,
autoExpandParent: this.autoExpandParent,
defaultExpandAll: this.defaultExpandAll,
filterNodeMethod: this.filterNodeMethod
});
this.root = this.store.root;
},
data() {
return {
store: null,
root: null,
currentNode: null
};
},
components: {
ElTreeNode: require('./tree-node.vue')
filterNodeMethod: Function,
accordion: Boolean
},
computed: {
@ -156,7 +140,31 @@
},
setChecked(data, checked, deep) {
this.store.setChecked(data, checked, deep);
},
handleChildNodeClick(node) {
this.broadcast('ElTreeNode', 'tree-node-click', node);
}
},
created() {
this.isTree = true;
this.store = new TreeStore({
key: this.nodeKey,
data: this.data,
lazy: this.lazy,
props: this.props,
load: this.load,
currentNodeKey: this.currentNodeKey,
checkStrictly: this.checkStrictly,
defaultCheckedKeys: this.defaultCheckedKeys,
defaultExpandedKeys: this.defaultExpandedKeys,
autoExpandParent: this.autoExpandParent,
defaultExpandAll: this.defaultExpandAll,
filterNodeMethod: this.filterNodeMethod
});
this.root = this.store.root;
}
};
</script>

View File

@ -354,4 +354,19 @@ describe('Tree', () => {
done();
}, 100);
});
it('accordion', done => {
vm = getTreeVm(':props="defaultProps" accordion');
const firstNode = vm.$el.querySelector('.el-tree-node__content');
const secondNode = vm.$el.querySelector('.el-tree-node:nth-child(2) .el-tree-node__content');
firstNode.click();
setTimeout(() => {
expect(vm.$el.querySelector('.el-tree-node').classList.contains('is-expanded')).to.true;
secondNode.click();
setTimeout(() => {
expect(vm.$el.querySelector('.el-tree-node').classList.contains('is-expanded')).to.false;
done();
}, DELAY);
}, DELAY);
});
});

501
yarn.lock

File diff suppressed because it is too large Load Diff