JavaScript按Key比较对象数组:匹配id与parentId添加子项问题
我懂你现在卡在哪了——你想把扁平的菜单数组转成嵌套的层级结构,但现在写的判断逻辑完全不对,所以根本没法匹配到父元素和子元素。咱们来一步步解决这个问题:
为什么你的当前判断不生效?
你写的data[i].id == data[i].parentId是在同一个菜单元素里比较它的id和parentId,除非某个菜单是自己的父节点(这显然不符合正常菜单的逻辑),否则这个条件永远会返回false。正确的逻辑应该是:找到另一个菜单元素,它的id等于当前元素的parentId,然后把当前元素作为子元素添加到那个父元素中。
正确的解决方案
我们可以用一个映射表(比如JavaScript的Map)来快速定位父元素,这样不用每次遍历整个数组,效率会高很多。具体步骤如下:
第一步:构建元素映射表
先把所有菜单元素用它的id作为键存起来,这样可以用O(1)的时间找到任意id对应的父元素。
第二步:生成嵌套结构
遍历所有菜单元素,根据parentId找到对应的父元素,把当前元素添加到父元素的children数组里;如果parentId是null,就把它作为根节点。
第三步:递归生成HTML结构
通过递归函数把嵌套好的数组转换成<ul>和<li>的HTML代码。
完整代码示例
let menuItems = [ { "id": "menu-0", "title": "Home", "parentId": "menu-1", "childCount": 0 }, { "id": "menu-1", "title": "About", "parentId": null, "childCount": 2 }, { "id": "menu-3", "title": "About Sub1", "parentId": "menu-1", "childCount": 2 }, { "id": "menu-5", "title": "About Sub2", "parentId": "menu-1", "childCount": 0 }, { "id": "menu-4", "title": "About Sub1 sub1", "parentId": "menu-3", "childCount": 0 }, { "id": "menu-6", "title": "Contact", "parentId": null, "childCount": 2 } ]; // 1. 创建映射表,同时给每个元素添加children属性 const menuMap = new Map(); const rootMenus = []; menuItems.forEach(item => { menuMap.set(item.id, { ...item, children: [] }); }); // 2. 构建嵌套结构 menuItems.forEach(item => { const currentItem = menuMap.get(item.id); if (item.parentId === null) { rootMenus.push(currentItem); } else { const parentItem = menuMap.get(item.parentId); // 确保父元素存在(避免数组里有无效的parentId) if (parentItem) { parentItem.children.push(currentItem); } } }); // 3. 递归生成HTML的函数 function generateMenuHTML(menuList) { if (menuList.length === 0) return ''; let html = '<ul>'; menuList.forEach(menu => { html += `<li>${menu.title}`; // 如果有子元素,递归生成子菜单 if (menu.children.length > 0) { html += generateMenuHTML(menu.children); } html += '</li>'; }); html += '</ul>'; return html; } // 生成HTML并插入到页面中 const finalMenuHTML = generateMenuHTML(rootMenus); document.body.innerHTML = finalMenuHTML;
代码说明
- 映射表
menuMap:让我们可以快速定位任意id对应的菜单元素,把时间复杂度从嵌套遍历的O(n²)降到了O(n),处理大数组时优势明显。 children属性:我们给每个菜单元素新增了这个数组,用来存储它的子元素,结构更清晰。- 递归生成HTML:不管你的菜单有多少层级(比如三级、四级菜单),这个函数都能正确生成对应的嵌套
<ul>和<li>结构。
内容的提问来源于stack exchange,提问作者Shirish Ardak
相关产品推荐
相关产品推荐

