layui tree 的 showSearch: true 仅渲染输入框,未实现过滤逻辑,需手动绑定事件、递归筛选数据、深拷贝隔离、缓存并恢复展开状态,且须处理大小写、字段名及防抖等细节。
layui tree 组件本身不支持模糊搜索,showsearch: true 只是插入一个输入框,没有绑定任何过滤逻辑——你输完回车或敲击,树不会自动响应,必须自己写数据过滤 + 重载。
为什么 tree.render() 加 showSearch 没反应
showSearch: true 是 layui 早期版本遗留的“半成品”配置,它只负责在容器上方渲染一个 <input>,但完全不监听输入事件、不触发过滤、也不提供高亮或展开能力。这不是你漏写了事件绑定,而是这个参数压根没实现后端逻辑。
- 检查控制台:输入后无任何
console.log或 DOM 变化,说明事件根本没挂上 - 不要试图用
tree.on('search(...)—— 官方 API 文档和源码里都不存在这个监听事件 - 若你看到别人 demo 能搜,那一定是他们手动绑定了
$('#searchInput').on('input', ...)并调用了tree.reload()
filterTreeData 函数必须递归标记父链
只筛出匹配关键词的节点是错的。比如搜“洪山”,{ title: '洪山区' } 匹配,但它的父节点“武汉”“湖北”必须保留,否则路径断裂,用户看不到完整层级。
- 每个节点需携带临时字段如
match: true,表示自身或任意子孙匹配 - 判断条件不能只看
node.title.includes(keyword),还要递归检查children是否有match === true的子项 - 过滤后生成新数组时,跳过
match === false && (!node.children || node.children.length === 0)的节点 - 别直接修改原始
data数组,用JSON.parse(JSON.stringify(data))或深拷贝工具隔离副作用
reload 后展开状态丢失怎么办
tree.reload() 会清空所有 DOM 状态(展开/折叠/选中),包括用户手动操作过的节点。如果你希望“搜完还保持之前展开的父节点”,得自己缓存并恢复。
- 在搜索前调用
tree.getChecked('id')或遍历 DOM 获取已展开节点 ID 列表($('[data-id]').filter(':visible').map(...)) - reload 完成后,在
done回调里逐个调用tree.expand(id, true) - 注意:如果树启用了
accordion: true,展开单个节点会自动收起兄弟节点,此时要按父子顺序倒序展开(先子后父) - 防抖必须加,否则连续输入触发多次
reload,DOM 重绘卡顿,且展开状态恢复逻辑可能被覆盖
最常被忽略的是大小写和字段名适配——node.name 在你的数据里可能是 nodeName 或 label,filterTreeData 里硬写 node.title 就会漏匹配;另外,高亮文本时直接操作 innerHTML 容易嵌套污染,应优先用 CSS mark 标签或独立 class 控制样式。这些细节不处理,搜索看起来“能动”,但实际业务中总在边缘 case 崩溃。


















