如何使用jQuery/JavaScript实现输入后搜索侧边栏菜单列表并修复无效代码
现有代码的问题
- 函数名大小写不匹配:HTML中输入框绑定的
onkeyup事件调用searchAppMenus(),但JS定义的函数名是searchAppmenus(),首字母M大小写不一致,导致事件触发时函数找不到。 - DOM选择逻辑错误:
document.getElementsByClassName("nav")返回的是所有包含nav类的元素集合,不能直接对集合调用getElementsByTagName方法,会直接报错。 - 显示逻辑有缺陷:
- 搜索时会把输入框所在的li也隐藏,导致无法继续输入
- 子菜单项匹配成功时,如果父级菜单被隐藏,匹配的子项也无法显示
- 直接取a标签的
innerHTML匹配,会把标签内的图标、样式类等内容也纳入搜索范围,匹配结果不符合预期
- 没有处理菜单层级的展开逻辑:匹配到子菜单时,需要自动展开父级折叠菜单才能正常看到结果
修复方案
替换原有JS代码为以下内容即可实现需求:
function searchAppMenus() { const input = document.getElementById("txt_search"); const filter = input.value.trim().toUpperCase(); const allMenuLi = document.querySelectorAll("#side-menu li"); // 先重置所有菜单项状态 allMenuLi.forEach(li => { li.style.display = ""; // 清空之前的展开状态,输入为空时恢复原生折叠效果 const childUl = li.querySelector("ul"); if(childUl) { childUl.classList.remove("in"); } }); // 输入为空直接返回,已经恢复默认状态 if(!filter) return; allMenuLi.forEach(li => { // 跳过输入框所在的li,避免输入框被隐藏 if(li.querySelector("#txt_search")) return; const aTag = li.querySelector("a"); if(!aTag) return; // 取纯文本匹配,排除标签内容干扰 const text = aTag.textContent.trim().toUpperCase(); const isMatch = text.indexOf(filter) > -1; if(isMatch) { // 匹配到的项显示,同时展开所有父级菜单 li.style.display = ""; // 遍历所有父级li,设置显示并展开折叠层 let parent = li.parentElement.closest("li"); while(parent) { parent.style.display = ""; const parentUl = parent.querySelector("ul.nav-second-level, ul.nav-third-level"); if(parentUl) { parentUl.classList.add("in"); } parent = parent.parentElement.closest("li"); } } else { // 不匹配的项隐藏 li.style.display = "none"; } }); }
修复后的逻辑完全符合要求:输入关键词时仅展示匹配的菜单项及其父级,自动展开折叠层;输入框清空后自动恢复菜单原始的折叠状态和结构。
内容的提问来源于stack exchange,提问作者Dream OC
相关产品推荐
相关产品推荐

