el-tree 保持搜索目标子节点展示

2,446 阅读1分钟

预览

2021-11-11.gif

前言

在使用 Element UI 的 el-tree 组件进行关键字过滤时,默认行为是:只展示匹配的节点本身,但其子节点不会被保留显示。这在实际业务中,可能会带来一些使用体验上的问题。例如,当一个父节点匹配关键字时,我们希望它的所有子节点也能一并展示出来,方便查看和操作。

本文将通过一个具体的示例,实现“el-tree 保持搜索目标子节点展示”的功能,并与 Element UI 默认的查询方式做对比。

实现思路

主要逻辑分为三部分:

  1. 通过 filterNode 函数自定义过滤规则;
  2. 如果一个节点匹配关键字,则递归调用函数 filter(),将其所有子节点设置为可见;
  3. 使用 $refs.tree.getNode(data) 获取节点实例,并手动设置 visible = true
<template>
  <div>
    <el-input
        placeholder="输入关键字进行过滤"
        v-model="filterText">
    </el-input>

    <div style="display: flex;justify-content: space-around">
      <div>
        <p style="color: red">修改后的查询</p>
        <el-tree :data="data1"
                 default-expand-all
                 :filter-node-method="filterNode"
                 ref="tree">
        </el-tree>
      </div>
      <div>
        <p style="color: red">element-ui 提供的查询</p>
        <el-tree :data="data1"
                 default-expand-all
                 :filter-node-method="filterNode1"
                 ref="tree1">
        </el-tree>
      </div>
    </div>
  </div>
</template>
<script>
export default {
  data() {
    return {
      filterText: '',
      data1: [{
        id: 100,
        label: '1263',
        children: [
          {
            id: 100,
            label: '852',
          }, {
            id: 111,
            label: '369',
          }, {
            id: 852,
            label: 'ki',
            children: [
              {
                id: 96,
                label: 'pp',
              }
            ]
          },
        ]
      }, {
        id: 1,
        label: '一级 1',
        children: [{
          id: 4,
          label: 'gf',
          children: [{
            id: 23,
            label: 'lk',
            children: [
              {
                id: 9,
                label: 'abnc'
              }, {
                id: 11,
                label: 'abnc43'
              }, {
                id: 10,
                label: '三级 1-1-2'
              }
            ]
          }]
        }]
      }, {
        id: 2,
        label: '一级 2',
        children: [{
          id: 5,
          label: '二级 2-1',
        }, {
          id: 6,
          label: '二级 2-2',
        }]
      }, {
        id: 3,
        label: '一级 3',
        children: [{
          id: 56,
          label: 'test',
          children: [
            {
              id: 7,
              label: '二级 3-1'
            }, {
              id: 8,
              label: '二级 3-2'
            }
          ]
        }]
      }],
    }
  },
  watch: {
    filterText(val) {
      this.$refs.tree.filter(val);
      this.$refs.tree1.filter(val);
    }
  },
  methods: {
    /**
     * 遍历节点
     **/
    filterNode(value, data) {
      if (data.label.indexOf(value) !== -1) {
        if (data.children && data.children.length) {
          this.$nextTick(() => {
            data.children.forEach((item) => {
              this.filter(item)
            })
          })
        }
        return true
      }
    },

    filterNode1(value, data) {
      if (data.label.indexOf(value) !== -1) {
        return true
      }
    },

    /**
     * 递归遍历设置子节点保持展示
     **/
    filter(data) {
      const node = this.$refs.tree.getNode(data)
      node.visible = true
      if (data.children && data.children.length) {
        data.children.forEach((item) => {
          this.filter(item)
        })
      }
    }
  },
}
</script>