element ui 的 tree.filter() 无反应,主因是漏配 filter-node-method 函数;该函数必须返回布尔值定义节点是否保留在 dom 中,且需正确引用字段、避免内联写法。

Element UI 的 filter 方法为什么没反应?
调用 tree.filter(keyword) 没效果,大概率是漏了 filter-node-method 配置。这个函数不是可选的——它定义“什么叫匹配”,没有它,filter() 就像喊人却不告诉名字。
常见错误现象:searchVal 改变但树节点不隐藏、不高亮、不展开父级;控制台无报错,但行为静默。
-
filter-node-method必须是函数引用,不能是内联箭头函数(否则 Vue 无法响应式追踪) - 函数返回
true表示该节点保留,false表示被过滤掉(注意:不是“是否高亮”,而是“是否出现在 DOM 中”) - 如果数据字段是
label,但实际源数据用的是name,data.name.indexOf(value) !== -1就会始终返回false - 别在
filter-node-method里做高亮逻辑——高亮应由 CSS 类或插槽模板控制,不是过滤职责
Layui tree.reload() 后节点全折叠了,怎么保持展开状态?
tree.reload() 是重绘整棵树,原始展开状态不会自动继承。你得手动标记哪些节点该展开,再传给新数据。
使用场景:用户搜“用户管理”,希望看到“系统设置 > 权限模块 > 用户管理”这条路径全部展开,而不是只显示“用户管理”一个孤节点。
- 递归遍历原始数据时,对每个匹配节点,沿
parent链路打上spread: true标记(或临时加个字段) - 过滤后的新数据中,把带
spread: true的节点及其所有祖先节点的spread设为true - 渲染时用
showLine: true+ 自定义isopen字段配合tree.render()的id参数,才能让 reload 后恢复展开 - 注意:Layui 的
tree不支持直接 setNodeSpread,必须靠数据驱动
原生 HTML+JS 实现搜索时,display: none 为什么让键盘导航失效?
用 style.display = 'none' 隐藏不匹配节点,会导致 tabindex 失效、focus() 找不到目标、屏幕阅读器跳过这些节点——这不是“隐藏”,是“移除可访问性”。
真正要做的不是隐藏,而是“视觉裁剪 + 语义保留”:
- 用
aria-hidden="true"标记不匹配节点,同时保持其在 DOM 中、保留tabindex="-1"和完整 ARIA 属性(如role="treeitem") - CSS 上用
opacity: 0; height: 0; overflow: hidden;替代display: none,避免布局塌陷和焦点丢失 - 必须同步更新
aria-expanded和aria-setsize/aria-posinset,否则键盘用户按 ↓ 键会跳过整个子树 - 搜索后调用
el.focus()到第一个匹配节点,而不是依赖 Tab 键顺序——因为被aria-hidden的节点仍占逻辑位置
大数据量树搜索卡顿,filter 递归太慢怎么办?
当树节点超 2000 个,每次输入都 filterTreeData(data, keyword) 全量递归,CPU 会明显卡住。这不是算法问题,是执行时机错了。
- 加防抖:搜索框
input事件里用setTimeout延迟 300ms 再触发过滤,避免每敲一个字都跑一遍 - 预建索引:启动时遍历一次全量数据,生成
Map<string node></string>,key 是所有可能被搜到的关键词(如node.label分词后的小写形式),查的时候 O(1) 拿到节点引用 - 不递归过滤,改用路径缓存:每个节点存一个
fullPath字符串(如"系统/权限/用户管理"),搜索时只做字符串includes(),快一个数量级 - 千万避免在
filter-node-method里做正则、分词、远程请求——它会在每个节点渲染时同步调用多次
最易被忽略的一点:搜索后没清空上次的高亮类名,导致 DOM 节点上堆砌几十个 highlight-xxx class,后续样式计算开销陡增。每次搜索前先 querySelectorAll('.highlight').forEach(el => el.classList.remove('highlight'))。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











