blog
blog copied to clipboard
ElementUI Tree 组件节点筛选显示所有后代节点
ElementUI 提供的 Tree
组件中有一个 filter-node-method
的 props, 可以配合 filter
方法来做树的查找筛选功能,具体的用法是:
<template>
<el-tree
ref="tree"
:data="data"
node-key="id"
:filter-node-method="filterTree"
/>
</template>
<script>
export default {
data() {
return [/* 一堆树结构数据 */]
},
methods: {
filterTree(value, data, node) {
return data.label.includes(value)
}
}
}
</script>
定义了 filterTree
方法后,使用 this.$refs.tree.filter(value)
方法可以对树节点进行筛选,这个 value
会传到 filterTree
中,对每个树节点调用一次该方法,根据返回的结果决定是否显示。
因此像上面的实现,只保证了命中的节点会被显示,当然 Element 保证了命中的节点的所有祖先节点都会被显示,不然很突兀地出现了嵌套在里面几级的节点也有点奇怪。然而经常会有一种需求,需要显示命中节点的所有后代节点,上面的写法就需要改造了。
最直观的想法是这里的返回不能只根据自己是否命中,应该考虑该节点的所有祖先节点是否命中。即:
是否显示 = 我命中了 || 我的祖先命中了
这里涉及到了状态保存与遍历方式的问题,于是观察一下 Element 对这个筛选 filter-node-method
的调用,不难发现这是个 DFS 的树遍历,正合我意啊。同时也在内部维护的 node
中找到了 node.visible
的标记,保存了筛选结果啊。
这样一来,这个方法就很好写了,但是要注意 Element 内部会给第一层的所有节点给一个虚拟的 root, 而且这个 root 的 visible 默认是 true 的,因此对第一层要做点特别处理:
function filterTree(value, data, node) {
// 第一层的节点,只需要考虑自己是否命中就好了
if (node.parent && !node.parent.parent) {
return data.label.includes(value)
}
return data.label.includes(value) || node.parent.visible
}
问题解决。