解决el-tree节点过滤不显示下级的问题
作者:桃子Jerry
这篇文章主要介绍了解决el-tree节点过滤不显示下级的问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
显示下级的方法
elementui的节点过滤默认是不显示下级的
代码在 :filter-node-method="filterNode" 中添加
let parentNode = node.parent // 父级node let labels = [node.label] // 当前node的名字 let level = 1 // 层级 while (level < node.level) { labels = [...labels, parentNode.label] // 当前node名字,父级node的名字 parentNode = parentNode.parent level++ } return labels.some(d => d.indexOf(value) !== -1)
这样就可以完美解决了子节点可以展开的问题:
我们需求方觉得还可以再优化
当搜索 “春天” 的时候,父子级都能匹配到,这个时候子级的支线节点 “桃子” 也会显示出来:
当搜索 “苦” 的时候,父子级都能匹配到,这个时候子级的其它无关苦的节点需要隐藏
代码仍然在el-tree官方原生的 :filter-node-method="filterNode" 方法里面加
思路
- 一、(当前是支线节点,也就是说兄弟有匹配到的)并且 (支线节点所有下级都匹配不到关键字)的情况
- 二、隐藏支线节点,包括所有下级的子节点才行,光隐藏支线节点没有用
nodesParentId:[] 方法外的变量默认空数组
if (node.level > 1) { // 把我和兄弟name整合到数组中 const info = findTreeIdObjFn(this.dataTree, 'id', data.parentId).children.map(d => d.name) // 判断兄弟有没有 if (info.some(d => d.indexOf(value) !== -1)) { // 兄弟能匹配到,自己没有匹配到 if (data.name.indexOf(value) === -1) { // 所有下级的 name 集合 const names = findCurNodeDescendantsFn(this.dataTree, 'id', data.id).map( d => findTreeIdObjFn(this.dataTree, 'id', d).name ) // 判断都没匹配到的情况 if (!names.some(d => d.indexOf(value) !== -1)) { // 把我和我下级所有id push到变量中,将当前支线节点隐藏 this.nodesParentId.push(...findCurNodeDescendantsFn(this.dataTree, 'id', data.id)) return false } } } } // 如果当前节点在支线节点名单中,则隐藏当前节点 if (this.nodesParentId.indexOf(data.id) !== -1) { return false }
全部代码:
filterNode(value, data, node) { // 校验没有数据情况 if (!value) { this.nodesParentId = [] this.$nextTick(() => { node.expanded = false }) return true } // 控制展开和收起 this.$nextTick(() => { node.expanded = false }) // 当前名字是否包含在上级父亲里 if (data.name.indexOf(value) !== -1) { this.$nextTick(() => { this.openSuperior(node) // 如果是第一级,直接打开当前级 if (!data.parentId) { node.expanded = true } }) } // 隐藏所有支线节点下面的所有子节点 // 思路: // (当前是支线节点,兄弟有匹配到的情况)并且 (支线节点所有下级都匹配不到)的情况 // 隐藏支线节点,包括所有下级的子节点才行,光隐藏支线节点没有用 if (node.level > 1) { // 把我和兄弟name整合到数组中 const info = findTreeIdObjFn(this.dataTree, 'id', data.parentId).children.map(d => d.name) // 判断兄弟有没有 if (info.some(d => d.indexOf(value) !== -1)) { // 兄弟能匹配到,自己没有匹配到 if (data.name.indexOf(value) === -1) { // 下级的 name 集合 const names = findCurNodeDescendantsFn(this.dataTree, 'id', data.id).map( d => findTreeIdObjFn(this.dataTree, 'id', d).name ) // 判断都没匹配到的情况 if (!names.some(d => d.indexOf(value) !== -1)) { // 把我和我下级所有id push到变量中,将当前支线节点隐藏 this.nodesParentId.push(...findCurNodeDescendantsFn(this.dataTree, 'id', data.id)) return false } } } } // 当前节点在支线节点名单中,则隐藏当前节点 if (this.nodesParentId.indexOf(data.id) !== -1) { return false } // 子级可被筛选到 let parentNode = node.parent // 父级node let labels = [node.label] // 当前node的名字 let level = 1 // 层级 while (level < node.level) { labels = [...labels, parentNode.label] // 当前node名字,父级node的名字 parentNode = parentNode.parent level++ } return labels.some(d => d.indexOf(value) !== -1) // 总结:之前没解决的是因为 只隐藏支线父节点是隐藏不掉的,隐藏父节点包括下面的所有子节点才能隐藏 }
openSuperior 方法
// 展开所有父级 openSuperior(node) { if (node.parent) { node.parent.expanded = true this.openSuperior(node.parent) } },
findTreeIdObjFn方法:
// 传入id(key)返回当前所在对象 /** * @param {*} data 树形结构全部数据 * @param {*} key 查找的key * @param {*} value 传入的key对应的value * @returns */ export const findTreeIdObjFn = (data, key, value) => { let temp = null ;(function fn(data, value) { data.forEach(item => { if (item[key] === value) { temp = item } if (item.children && item.children.length > 0) { fn(item.children, value) } }) })(data, value) return temp }
findCurNodeDescendantsFn方法:
// 找到传入tree数据当前节点的id及所有子孙的id(key)集合 /** * @param {*} data tree数据 * @param {*} key 要查找的key * @param {*} value key对应的value * @returns */ export const findCurNodeDescendantsFn = (data, key, value) => { const obj = findTreeIdObjFn(data, key, value) const ids = [] ;(function selfRunFn(obj) { ids.push(obj[key]) if (obj.children && obj.children.length > 0) { obj.children.forEach(x => { selfRunFn(x) }) } })(obj) return ids }
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。