多级深度菜单含指定关键词项的通用过滤方案咨询
多层嵌套菜单的通用筛选方案
问题背景
我有如下结构的多层嵌套菜单:
item1 item2 childrenOfItem2 childrenOfchildren1 childrenOfchildren2 HELLOchildrenOfchildren3 childrenOfItem2 childrenOfItem2 HELLOitem3 item4 childrenOfItem4 HELLOchildrenOfItem4 item5 childrenOfItem5
需要筛选出所有标题包含"HELLO"的菜单项,当前采用多层嵌套循环的方式实现,但如果菜单新增层级,该方案就会失效,求更通用的实现方式。
当前实现的问题
以下是当前的实现代码,核心问题是硬编码了三层循环,只能处理固定三级的菜单结构,一旦菜单新增层级,代码就无法覆盖:
const matchName = (item, word) => item?.title?.toLowerCase()?.includes(word?.toLowerCase()); const filter = (word = "", arr = []) => { const listOfItems = []; arr.forEach((item) => { if (matchName(item, word)) { listOfItems.push(item); } else if (item?.children?.length > 0) { const newSubItem = []; item.children.forEach((subItem) => { if (matchName(subItem, word)) { newSubItem.push(subItem); } else if (subItem?.children?.length > 0) { const newSubSubItems = []; subItem.children.forEach((subsubItem) => { if (matchName(subsubItem, word)) { newSubSubItems.push(subsubItem); } }); if (newSubSubItems?.length > 0) { newSubItem.push({ ...subItem, children: newSubSubItems }); } } }); if (newSubItem?.length > 0) { listOfItems.push({ ...item, children: newSubItem }); } } }); return listOfItems; };
通用解决方案:递归实现
使用递归函数可以处理任意层级的嵌套菜单,不管菜单新增多少层,代码都不需要修改。核心思路是:遍历当前层级的每个项,若当前项匹配则直接保留;若不匹配但有子菜单,就递归处理子菜单,若子菜单有匹配结果,则保留当前项并替换为筛选后的子菜单。
完整递归实现代码
const matchName = (item, word) => item?.title?.toLowerCase()?.includes(word?.toLowerCase()); const filterMenu = (word = "", arr = []) => { const result = []; arr.forEach(item => { // 复制当前项,避免修改原始数据 const currentItem = { ...item }; // 当前项匹配关键词,直接加入结果 if (matchName(currentItem, word)) { result.push(currentItem); } else { // 递归处理子菜单 if (currentItem.children?.length > 0) { const filteredChildren = filterMenu(word, currentItem.children); // 子菜单有匹配结果时,保留当前项并更新子菜单 if (filteredChildren.length > 0) { currentItem.children = filteredChildren; result.push(currentItem); } } } }); return result; };
测试示例
基于你提供的示例数据,修改部分项的标题加入"HELLO"进行测试:
// 带测试数据的菜单 const testList = [ { id: "41", title: "sample", children: [ { id: "42", title: "sample", children: [ { id: "43", title: "sample", children: [] }, { id: "44", title: "sample", children: [] }, { id: "45", title: "HELLOsample", children: [] }, ], }, { id: "46", title: "sample", children: [ { id: "47", title: "sample", children: [] }, { id: "48", title: "sample", children: [] }, ], }, ], }, { id: "29", title: "sample", children: [ { id: "30", title: "sample", children: [] }, { id: "49", title: "HELLOsample", children: [] }, { id: "31", title: "sample", children: [] }, ], }, ]; // 调用筛选函数 const filteredResult = filterMenu("HELLO", testList); console.log(filteredResult);
输出结果说明
最终结果会包含:
- 第一个父级项(id:41),其子项仅保留id:42的项,而id:42的子项仅保留匹配的id:45项
- 第二个父级项(id:29),其子项仅保留匹配的id:49项
不管后续菜单新增多少层级,递归函数都会自动遍历所有子节点,无需修改代码。
内容的提问来源于stack exchange,提问作者Ewejnog
相关产品推荐
相关产品推荐

