el-tree节点过滤不显示下级问题怎么解决

发布时间:2023-05-05 16:40:18 作者:iii
来源:亿速云 阅读:384

el-tree节点过滤不显示下级问题怎么解决

引言

在前端开发中,Element UI 是一个非常流行的 Vue.js 组件库,其中的 el-tree 组件常用于展示树形结构的数据。然而,在使用 el-tree 进行节点过滤时,可能会遇到一个问题:过滤后的节点不显示其下级节点。这个问题可能会影响用户体验,因此需要找到合适的解决方案。

本文将详细探讨 el-tree 节点过滤不显示下级问题的原因,并提供多种解决方案。我们将从基础概念入手,逐步深入,最终给出完整的代码示例和优化建议。

1. el-tree 组件简介

1.1 什么是 el-tree

el-tree 是 Element UI 提供的一个树形控件,用于展示层次结构的数据。它支持节点的展开、折叠、选中、拖拽等操作,非常适合用于文件目录、组织结构等场景。

1.2 el-tree 的基本用法

<template>
  <el-tree
    :data="treeData"
    :props="defaultProps"
    @node-click="handleNodeClick"
  ></el-tree>
</template>

<script>
export default {
  data() {
    return {
      treeData: [
        {
          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',
                },
              ],
            },
          ],
        },
      ],
      defaultProps: {
        children: 'children',
        label: 'label',
      },
    };
  },
  methods: {
    handleNodeClick(data) {
      console.log(data);
    },
  },
};
</script>

1.3 el-tree 的过滤功能

el-tree 提供了 filter-node-method 属性,用于自定义节点过滤的逻辑。通过这个属性,我们可以实现根据用户输入的关键词来过滤树节点。

<template>
  <div>
    <el-input v-model="filterText" placeholder="输入关键字进行过滤" />
    <el-tree
      :data="treeData"
      :props="defaultProps"
      :filter-node-method="filterNode"
      ref="tree"
    ></el-tree>
  </div>
</template>

<script>
export default {
  data() {
    return {
      treeData: [
        {
          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',
                },
              ],
            },
          ],
        },
      ],
      defaultProps: {
        children: 'children',
        label: 'label',
      },
      filterText: '',
    };
  },
  watch: {
    filterText(val) {
      this.$refs.tree.filter(val);
    },
  },
  methods: {
    filterNode(value, data) {
      if (!value) return true;
      return data.label.indexOf(value) !== -1;
    },
  },
};
</script>

2. 问题描述

在使用 el-tree 进行节点过滤时,可能会遇到一个问题:过滤后的节点不显示其下级节点。例如,当用户输入“二级”进行过滤时,只有“二级”节点会被显示,而其下级节点(如“三级 1-1-1”)则不会被显示。

2.1 问题复现

<template>
  <div>
    <el-input v-model="filterText" placeholder="输入关键字进行过滤" />
    <el-tree
      :data="treeData"
      :props="defaultProps"
      :filter-node-method="filterNode"
      ref="tree"
    ></el-tree>
  </div>
</template>

<script>
export default {
  data() {
    return {
      treeData: [
        {
          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',
                },
              ],
            },
          ],
        },
      ],
      defaultProps: {
        children: 'children',
        label: 'label',
      },
      filterText: '',
    };
  },
  watch: {
    filterText(val) {
      this.$refs.tree.filter(val);
    },
  },
  methods: {
    filterNode(value, data) {
      if (!value) return true;
      return data.label.indexOf(value) !== -1;
    },
  },
};
</script>

在上述代码中,当用户输入“二级”进行过滤时,只有“二级”节点会被显示,而其下级节点(如“三级 1-1-1”)则不会被显示。

2.2 问题分析

这个问题的根本原因在于 el-tree 的过滤逻辑。默认情况下,el-tree 只会显示匹配过滤条件的节点,而不会显示其下级节点。即使下级节点本身也匹配过滤条件,也不会被显示。

3. 解决方案

3.1 方案一:递归过滤

我们可以通过递归的方式,在过滤时不仅检查当前节点是否匹配过滤条件,还要检查其下级节点是否匹配。如果下级节点匹配,则将其上级节点也显示出来。

<template>
  <div>
    <el-input v-model="filterText" placeholder="输入关键字进行过滤" />
    <el-tree
      :data="filteredTreeData"
      :props="defaultProps"
      ref="tree"
    ></el-tree>
  </div>
</template>

<script>
export default {
  data() {
    return {
      treeData: [
        {
          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',
                },
              ],
            },
          ],
        },
      ],
      defaultProps: {
        children: 'children',
        label: 'label',
      },
      filterText: '',
    };
  },
  computed: {
    filteredTreeData() {
      return this.filterTree(this.treeData, this.filterText);
    },
  },
  methods: {
    filterTree(treeData, filterText) {
      return treeData.filter(node => {
        if (node.children) {
          node.children = this.filterTree(node.children, filterText);
        }
        return (
          node.label.indexOf(filterText) !== -1 ||
          (node.children && node.children.length > 0)
        );
      });
    },
  },
};
</script>

3.2 方案二:使用 filter-node-method 自定义过滤逻辑

我们可以在 filter-node-method 中自定义过滤逻辑,确保在过滤时不仅检查当前节点,还要检查其下级节点。

<template>
  <div>
    <el-input v-model="filterText" placeholder="输入关键字进行过滤" />
    <el-tree
      :data="treeData"
      :props="defaultProps"
      :filter-node-method="filterNode"
      ref="tree"
    ></el-tree>
  </div>
</template>

<script>
export default {
  data() {
    return {
      treeData: [
        {
          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',
                },
              ],
            },
          ],
        },
      ],
      defaultProps: {
        children: 'children',
        label: 'label',
      },
      filterText: '',
    };
  },
  watch: {
    filterText(val) {
      this.$refs.tree.filter(val);
    },
  },
  methods: {
    filterNode(value, data, node) {
      if (!value) return true;
      const contains = data.label.indexOf(value) !== -1;
      if (contains) return true;
      if (node.childNodes) {
        return node.childNodes.some(child => this.filterNode(value, child.data, child));
      }
      return false;
    },
  },
};
</script>

3.3 方案三:使用 expand-on-click-node 属性

我们可以通过设置 expand-on-click-node 属性为 false,来防止节点在点击时自动展开。这样,用户需要手动展开节点,从而避免过滤后下级节点不显示的问题。

<template>
  <div>
    <el-input v-model="filterText" placeholder="输入关键字进行过滤" />
    <el-tree
      :data="treeData"
      :props="defaultProps"
      :filter-node-method="filterNode"
      :expand-on-click-node="false"
      ref="tree"
    ></el-tree>
  </div>
</template>

<script>
export default {
  data() {
    return {
      treeData: [
        {
          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',
                },
              ],
            },
          ],
        },
      ],
      defaultProps: {
        children: 'children',
        label: 'label',
      },
      filterText: '',
    };
  },
  watch: {
    filterText(val) {
      this.$refs.tree.filter(val);
    },
  },
  methods: {
    filterNode(value, data) {
      if (!value) return true;
      return data.label.indexOf(value) !== -1;
    },
  },
};
</script>

3.4 方案四:使用 default-expand-all 属性

我们可以通过设置 default-expand-all 属性为 true,来默认展开所有节点。这样,即使过滤后下级节点也会被显示。

<template>
  <div>
    <el-input v-model="filterText" placeholder="输入关键字进行过滤" />
    <el-tree
      :data="treeData"
      :props="defaultProps"
      :filter-node-method="filterNode"
      :default-expand-all="true"
      ref="tree"
    ></el-tree>
  </div>
</template>

<script>
export default {
  data() {
    return {
      treeData: [
        {
          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',
                },
              ],
            },
          ],
        },
      ],
      defaultProps: {
        children: 'children',
        label: 'label',
      },
      filterText: '',
    };
  },
  watch: {
    filterText(val) {
      this.$refs.tree.filter(val);
    },
  },
  methods: {
    filterNode(value, data) {
      if (!value) return true;
      return data.label.indexOf(value) !== -1;
    },
  },
};
</script>

4. 优化建议

4.1 性能优化

在处理大量数据时,递归过滤可能会导致性能问题。为了提高性能,可以考虑以下优化措施:

4.2 用户体验优化

5. 总结

el-tree 节点过滤不显示下级节点的问题,主要是由于默认的过滤逻辑只检查当前节点是否匹配过滤条件。通过递归过滤、自定义过滤逻辑、设置 expand-on-click-nodedefault-expand-all 属性,我们可以有效地解决这个问题。

在实际开发中,我们需要根据具体需求选择合适的解决方案,并结合性能优化和用户体验优化,提供更好的用户界面。

6. 参考代码

以下是完整的参考代码,结合了递归过滤和自定义过滤逻辑:

<template>
  <div>
    <el-input v-model="filterText" placeholder="输入关键字进行过滤" />
    <el-tree
      :data="filteredTreeData"
      :props="defaultProps"
      ref="tree"
    ></el-tree>
  </div>
</template>

<script>
export default {
  data() {
    return {
      treeData: [
        {
          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',
                },
              ],
            },
          ],
        },
      ],
      defaultProps: {
        children: 'children',
        label: 'label',
      },
      filterText: '',
    };
  },
  computed: {
    filteredTreeData() {
      return this.filterTree(this.treeData, this.filterText);
    },
  },
  methods: {
    filterTree(treeData, filterText) {
      return treeData.filter(node => {
        if (node.children) {
          node.children = this.filterTree(node.children, filterText);
        }
        return (
          node.label.indexOf(filterText) !== -1 ||
          (node.children && node.children.length > 0)
        );
      });
    },
  },
};
</script>

通过以上代码,我们可以实现 el-tree 节点过滤时显示下级节点的功能,从而提升用户体验。

推荐阅读:
  1. Apache Hudi 异步Compaction部署方式有哪些
  2. java中new一个对象和clone一个对象性能有什么区别

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

el-tree

上一篇:Python怎么实现监控屏幕界面内容变化并发送通知

下一篇:Go语言otns源码分析

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》