Browse Source

Tree: add filter-node-method prop & filter method.

Furybean 8 years ago
parent
commit
59293a219e

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

@@ -230,6 +230,7 @@ Used for node selection. In the following example, data for each layer is acquir
 | show-checkbox | whether node is selectable | boolean | — | false |
 | 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) | - | - |
 
 ### props
 | Attribute      | Description          | Type      | Accepted Values       | Default  |
@@ -241,6 +242,7 @@ Used for node selection. In the following example, data for each layer is acquir
 `Tree` has the following method, which returns the currently selected array of nodes.
 | Method      | Description    | Parameters     |
 |---------- |-------- |---------- |
+| filter | filter all tree nodes, filtered nodes will be hidden | Accept a parameter which will be used as first parameter for filter-node-method |
 | getCheckedNodes | If the node can be selected (`show-checkbox` is `true`), it returns the currently selected array of nodes | Accept a boolean type parameter whose default value is `false`. <br>If the parameter is `true`, it only returns the currently selected array of sub-nodes.|
 | setCheckedNodes | set certain nodes to be checked, only works when `node-key` is assigned | an array of nodes to be checked |
 | getCheckedKeys | If the node can be selected (`show-checkbox` is `true`), it returns the currently selected array of node's keys | (leafOnly) Accept a boolean type parameter whose default value is `true`. <br>If the parameter is `true`, it only returns the currently selected array of sub-nodes.|

+ 2 - 0
examples/docs/zh-CN/tree.md

@@ -242,6 +242,7 @@
 | show-checkbox | 节点是否可被选择 | boolean | — | false |
 | check-strictly | 在显示复选框的情况下,是否严格的遵循父子不互相关联的做法,默认为 false | boolean | — | false |
 | default-checked-keys | 默认勾选的节点的 key 的数组 | array | — | — |
+| filter-node-method | 对树节点进行筛选时执行的方法,返回 true 表示这个节点可以显示,返回 false 则表示这个节点会被隐藏 | Function(value, data, node) | - | - |
 
 ### props
 | 参数      | 说明          | 类型      | 可选值                           | 默认值  |
@@ -253,6 +254,7 @@
 `Tree` 拥有如下方法,返回目前被选中的节点数组:
 | 方法名 | 说明 | 参数 |
 |------|--------|------|
+| filter | 对树节点进行筛选操作 | 接收一个任意类型的参数,该参数会在 filter-node-method 中作为第一个参数 |
 | getCheckedNodes | 若节点可被选择(即 `show-checkbox` 为 `true`),<br>则返回目前被选中的节点所组成的数组 | (leafOnly) 接收一个 boolean 类型的参数,若为 `true` 则<br>仅返回被选中的叶子节点,默认值为 `false` |
 | setCheckedNodes | 设置目前勾选的节点,使用此方法必须设置 node-key 属性 | (nodes) 接收勾选节点数据的数组 |
 | getCheckedKeys | 若节点可被选择(即 `show-checkbox` 为 `true`),<br>则返回目前被选中的节点所组成的数组 | (leafOnly) 接收一个 boolean 类型的参数,若为 `true` 则仅返回被选中的叶子节点的 keys,默认值为 `true` |

+ 1 - 0
packages/tree/src/model/node.js

@@ -50,6 +50,7 @@ export default class Node {
     this.data = null;
     this.expanded = false;
     this.parent = null;
+    this.visible = true;
 
     for (let name in options) {
       if (options.hasOwnProperty(name)) {

+ 31 - 0
packages/tree/src/model/tree.js

@@ -26,6 +26,37 @@ export default class Tree {
     }
   }
 
+  filter(value) {
+    const filterNodeMethod = this.filterNodeMethod;
+    const traverse = function(node) {
+      const childNodes = node.root ? node.root.childNodes : node.childNodes;
+
+      childNodes.forEach((child) => {
+        child.visible = filterNodeMethod.call(child, value, child.data, child);
+
+        traverse(child);
+      });
+
+      if (!node.visible && childNodes.length) {
+        let allHidden = true;
+
+        childNodes.forEach((child) => {
+          if (child.visible) allHidden = false;
+        });
+
+        if (node.root) {
+          node.root.visible = allHidden === false;
+        } else {
+          node.visible = allHidden === false;
+        }
+      }
+
+      if (node.visible && !node.isLeaf) node.expand();
+    };
+
+    traverse(this);
+  }
+
   setData(newVal) {
     const instanceChanged = newVal !== this.root.data;
     this.root.setData(newVal);

+ 2 - 1
packages/tree/src/tree-node.vue

@@ -1,7 +1,8 @@
 <template>
   <div class="el-tree-node"
     @click.stop="handleClick"
-    :class="{ 'is-expanded': childNodeRendered && expanded, 'is-current': $tree.currentNode === _self }">
+    v-show="node.visible"
+    :class="{ 'is-expanded': childNodeRendered && expanded, 'is-current': $tree.currentNode === _self, 'is-hidden': !node.visible }">
     <div class="el-tree-node__content"
       :style="{ 'padding-left': (node.level - 1) * 16 + 'px' }"
       @click="handleExpandIconClick">

+ 8 - 2
packages/tree/src/tree.vue

@@ -57,7 +57,8 @@
         default: false
       },
       highlightCurrent: Boolean,
-      load: Function
+      load: Function,
+      filterNodeMethod: Function
     },
 
     created() {
@@ -73,7 +74,8 @@
         defaultCheckedKeys: this.defaultCheckedKeys,
         defaultExpandedKeys: this.defaultExpandedKeys,
         autoExpandParent: this.autoExpandParent,
-        defaultExpandAll: this.defaultExpandAll
+        defaultExpandAll: this.defaultExpandAll,
+        filterNodeMethod: this.filterNodeMethod
       });
     },
 
@@ -109,6 +111,10 @@
     },
 
     methods: {
+      filter(value) {
+        if (!this.filterNodeMethod) throw new Error('[Tree] filterNodeMethod is required when filter');
+        this.tree.filter(value);
+      },
       getCheckedNodes(leafOnly) {
         return this.tree.getCheckedNodes(leafOnly);
       },

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

@@ -127,6 +127,25 @@ describe('Tree', () => {
     expect(vm.$el.querySelectorAll('.el-tree-node.is-expanded').length).to.equal(2);
   });
 
+  it('filter-node-method', (done) => {
+    vm = getTreeVm(':props="defaultProps" :filter-node-method="filterNode"', {
+      methods: {
+        filterNode(value, data) {
+          if (!value) return true;
+          return data.label.indexOf(value) !== -1;
+        }
+      }
+    });
+
+    const tree = vm.$refs.tree;
+    tree.filter('2-1');
+
+    setTimeout(() => {
+      expect(tree.$el.querySelectorAll('.el-tree-node.is-hidden').length).to.equal(7);
+      done();
+    }, 100);
+  });
+
   it('autoExpandParent = true', () => {
     vm = getTreeVm(':props="defaultProps" :default-expanded-keys="defaultExpandedKeys" node-key="id"', {
       created() {