FuryBean 7 роки тому
батько
коміт
6bef614c01

+ 5 - 0
examples/docs/en-US/tree.md

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

+ 5 - 0
examples/docs/es/tree.md

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

+ 8 - 1
examples/docs/zh-CN/tree.md

@@ -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
 | 事件名称           | 说明             | 回调参数                                     |

+ 19 - 2
packages/tree/src/model/node.js

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

+ 5 - 2
packages/tree/src/model/tree-store.js

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

+ 3 - 6
packages/tree/src/tree-node.vue

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

+ 18 - 6
packages/tree/src/tree.vue

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

+ 48 - 0
test/unit/specs/tree.spec.js

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