add api for tree (#9718)

pull/9751/head
FuryBean 2018-02-09 10:28:43 +08:00 committed by 杨奕
parent d32beea1fe
commit 6bef614c01
8 changed files with 111 additions and 17 deletions

View File

@ -1042,6 +1042,11 @@ Only one node among the same level can be expanded at one time.
| getCurrentNode | return the highlight node (null if no node is highlighted) | — |
| setCurrentKey | set highlighted node by key, only works when `node-key` is assigned | (key) the node's key to be highlighted |
| setCurrentNode | set highlighted node, only works when `node-key` is assigned | (node) the node to be highlighted |
| getNode | get node by data or key | (data) the node's data or key |
| remove | remove a node | (data) the node's data or node to be delete |
| append | append a child node for a node in tree | (data, parentNode) Accept two parameters: 1. child node's data 2. parent node's data, key or node |
| insertBefore | insert a node before a node in tree | (data, refNode) (data, parentNode) Accept two parameters: 1. sibling node's data 2. reference node's data, key or node |
| insertAfter | insert a node after a node in tree | (data, refNode) 1. sibling node's data 2. reference node's data, key or node |
### Events
| Event Name | Description | Parameters |

View File

@ -1040,6 +1040,11 @@ Solo puede ser expandido un nodo del mismo nivel a la vez.
| getCurrentNode | devuelve el nodo resaltado (null si no hay ninguno) | — |
| setCurrentKey | establece el nodo resaltado por la clave, solo funciona si `node-key` está asignado | (key) la clave del nodo a ser resaltado |
| setCurrentNode | establece el nodo resaltado, solo funciona si `node-key` está asignado | (node) nodo a ser resaltado |
| getNode | get node by data or key | (data) the node's data or key |
| remove | remove a node | (data) the node's data or node to be delete |
| append | append a child node for a node in tree | (data, parentNode) Accept two parameters: 1. child node's data 2. parent node's data, key or node |
| insertBefore | insert a node before a node in tree | (data, refNode) (data, parentNode) Accept two parameters: 1. sibling node's data 2. reference node's data, key or node |
| insertAfter | insert a node after a node in tree | (data, refNode) 1. sibling node's data 2. reference node's data, key or node |
### Eventos
| Nombre del evento | Descripción | Parámetros |

View File

@ -1027,7 +1027,9 @@
| isLeaf | 指定节点是否为叶子节点 | boolean, function(data, node) | — | — |
### 方法
`Tree` 拥有如下方法,返回目前被选中的节点数组:
`Tree` 内部使用了 Node 类型的对象来包装用户传入的数据,用来保存目前节点的状态。
`Tree` 拥有如下方法:
| 方法名 | 说明 | 参数 |
| --------------- | ---------------------------------------- | ---------------------------------------- |
| filter | 对树节点进行筛选操作 | 接收一个任意类型的参数,该参数会在 filter-node-method 中作为第一个参数 |
@ -1041,6 +1043,11 @@
| getCurrentNode | 获取当前被选中节点的 node若没有节点被选中则返回 null | — |
| setCurrentKey | 通过 key 设置某个节点的当前选中状态,使用此方法必须设置 node-key 属性 | (key) 待被选节点的 key |
| setCurrentNode | 通过 node 设置某个节点的当前选中状态,使用此方法必须设置 node-key 属性 | (node) 待被选节点的 node |
| getNode | 根据 data 或者 key 拿到 Tree 组件中的 node | (data) 要获得 node 的 key 或者 data |
| remove | 删除 Tree 中的一个节点 | (data) 要删除的节点的 data、key 或者 node |
| append | 为 Tree 中的一个节点追加一个子节点 | (data, parentNode) 接收两个参数1. 要追加的子节点的 data 2. 子节点的 parent 的 data、key 或者 node |
| insertBefore | 为 Tree 的一个节点的前面增加一个节点 | (data, refNode) 接收两个参数1. 要增加的节点的 data 2. 要增加的节点的后一个节点的 data、key 或者 node |
| insertAfter | 为 Tree 的一个节点的后面增加一个节点 | (data, refNode) 接收两个参数1. 要增加的节点的 data 2. 要增加的节点的前一个节点的 data、key 或者 node |
### Events
| 事件名称 | 说明 | 回调参数 |

View File

@ -168,10 +168,20 @@ export default class Node {
return getPropertyFromData(this, 'disabled');
}
insertChild(child, index) {
insertChild(child, index, batch) {
if (!child) throw new Error('insertChild error: child is required.');
if (!(child instanceof Node)) {
if (!batch) {
const children = this.getChildren() || [];
if (children.indexOf(child.data) === -1) {
if (typeof index === 'undefined' || index < 0) {
children.push(child.data);
} else {
children.splice(index, 0, child.data);
}
}
}
objectAssign(child, {
parent: this,
store: this.store
@ -208,6 +218,12 @@ export default class Node {
}
removeChild(child) {
const children = this.getChildren() || [];
const dataIndex = children.indexOf(child.data);
if (dataIndex > -1) {
children.splice(dataIndex, 1);
}
const index = this.childNodes.indexOf(child);
if (index > -1) {
@ -263,7 +279,7 @@ export default class Node {
doCreateChildren(array, defaultProps = {}) {
array.forEach((item) => {
this.insertChild(objectAssign({ data: item }, defaultProps));
this.insertChild(objectAssign({ data: item }, defaultProps), undefined, true);
});
}
@ -342,6 +358,7 @@ export default class Node {
}
getChildren() { // this is data
if (this.level === 0) return this.data;
const data = this.data;
if (!data) return null;

View File

@ -64,15 +64,18 @@ export default class TreeStore {
setData(newVal) {
const instanceChanged = newVal !== this.root.data;
this.root.setData(newVal);
if (instanceChanged) {
this.root.setData(newVal);
this._initDefaultCheckedNodes();
} else {
this.root.updateChildren();
}
}
getNode(data) {
if (data instanceof Node) return data;
const key = typeof data !== 'object' ? data : getNodeKey(this.key, data);
return this.nodesMap[key];
return this.nodesMap[key] || null;
}
insertBefore(data, refData) {

View File

@ -64,6 +64,7 @@
import ElCollapseTransition from 'element-ui/src/transitions/collapse-transition';
import ElCheckbox from 'element-ui/packages/checkbox';
import emitter from 'element-ui/src/mixins/emitter';
import { getNodeKey } from './model/util';
export default {
name: 'ElTreeNode',
@ -140,12 +141,8 @@
},
methods: {
getNodeKey(node, index) {
const nodeKey = this.tree.nodeKey;
if (nodeKey && node) {
return node.data[nodeKey];
}
return index;
getNodeKey(node) {
return getNodeKey(this.tree.nodeKey, node.data);
},
handleSelectChange(checked, indeterminate) {

View File

@ -21,6 +21,7 @@
<script>
import TreeStore from './model/tree-store';
import { getNodeKey } from './model/util';
import ElTreeNode from './tree-node.vue';
import {t} from 'element-ui/src/locale';
import emitter from 'element-ui/src/mixins/emitter';
@ -142,12 +143,8 @@
if (!this.filterNodeMethod) throw new Error('[Tree] filterNodeMethod is required when filter');
this.store.filter(value);
},
getNodeKey(node, index) {
const nodeKey = this.nodeKey;
if (nodeKey && node) {
return node.data[nodeKey];
}
return index;
getNodeKey(node) {
return getNodeKey(this.nodeKey, node.data);
},
getNodePath(data) {
if (!this.nodeKey) throw new Error('[Tree] nodeKey is required in getNodePath');
@ -195,6 +192,21 @@
if (!this.nodeKey) throw new Error('[Tree] nodeKey is required in setCurrentKey');
this.store.setCurrentNodeKey(key);
},
getNode(data) {
return this.store.getNode(data);
},
remove(data) {
this.store.remove(data);
},
append(data, parentNode) {
this.store.append(data, parentNode);
},
insertBefore(data, refNode) {
this.store.insertBefore(data, refNode);
},
insertAfter(data, refNode) {
this.store.insertAfter(data, refNode);
},
handleNodeExpand(nodeData, node, instance) {
this.broadcast('ElTreeNode', 'tree-node-expand', node);
this.$emit('node-expand', nodeData, node, instance);

View File

@ -455,6 +455,54 @@ describe('Tree', () => {
});
});
it('getNode', () => {
vm = getTreeVm(':props="defaultProps" node-key="id"');
const tree = vm.$children[0];
const node = tree.getNode(111);
expect(node.data.id).to.equal(111);
});
it('remove', (done) => {
vm = getTreeVm(':props="defaultProps" node-key="id"');
const tree = vm.$children[0];
tree.remove(1);
vm.$nextTick(() => {
expect(vm.data[0].id).to.equal(2);
expect(tree.getNode(1)).to.equal(null);
done();
});
});
it('append', () => {
vm = getTreeVm(':props="defaultProps" node-key="id"');
const tree = vm.$children[0];
const nodeData = { id: 88, label: '88' };
tree.append(nodeData, tree.getNode(1));
expect(vm.data[0].children.length).to.equal(2);
expect(tree.getNode(88).data).to.equal(nodeData);
});
it('insertBefore', () => {
vm = getTreeVm(':props="defaultProps" node-key="id"');
const tree = vm.$children[0];
const nodeData = { id: 88, label: '88' };
tree.insertBefore(nodeData, tree.getNode(11));
expect(vm.data[0].children.length).to.equal(2);
expect(vm.data[0].children[0]).to.equal(nodeData);
expect(tree.getNode(88).data).to.equal(nodeData);
});
it('insertAfter', () => {
vm = getTreeVm(':props="defaultProps" node-key="id"');
const tree = vm.$children[0];
const nodeData = { id: 88, label: '88' };
tree.insertAfter(nodeData, tree.getNode(11));
expect(vm.data[0].children.length).to.equal(2);
expect(vm.data[0].children[1]).to.equal(nodeData);
expect(tree.getNode(88).data).to.equal(nodeData);
});
it('set disabled checkbox', done => {
vm = getDisableTreeVm(':props="defaultProps" show-checkbox node-key="id" default-expand-all');
const node = document.querySelectorAll('.el-tree-node__content')[2];