如何生成带唯一组名的独立<li>元素?代码优化求助
问题描述
需要生成带唯一组名的独立<li>元素,现有JavaScript代码通过循环数组生成<ul>内容时会重复显示组名,期望实现组名仅显示一次、同组项归属对应组的效果:
- 当前问题:每个带分组的条目都会重复输出对应的组名
<li>,比如"Popular Product Areas"会跟着每个子项重复出现多次 - 预期效果:每个组名仅显示一次,下方列出该组所有子项;无组的条目直接单独显示
原代码如下:
let chosenResultsUl = document.getElementsByClassName("chosen-results"); const array1 = [ { group: null, id: "all-categories", title: "Search All", searchURL: "", typeAheadURL: "", include: null, exclude: null, activation: null, }, { group: null, id: "trial-catalog", title: "Aspire Free Products", searchURL: "", typeAheadURL: "", include: null, exclude: null, activation: "", }, { group: "Popular Product Areas", id: "taqman-assays", title: "TaqMan Assays", searchURL: "", typeAheadURL: "", include: null, exclude: "", activation: "", }, { group: "Popular Product Areas", id: "gene-exp-assays", title: "Gene Expression", searchURL: "", typeAheadURL: "", include: "", exclude: "", activation: "", }, { group: "Popular Product Areas", id: "microbe-abr-detection", title: "Microbe & ABR Detection", searchURL: "", typeAheadURL: "", include: "", exclude: "", activation: null, }, { group: "Doc Support", id: "microbe-detection", title: "Microbe Detection", searchURL: "", typeAheadURL: "", include: "", exclude: "", activation: "", }, { group: "Doc Support", id: "antibiotic-resistance", title: "Antibiotic Resistance", searchURL: "", typeAheadURL: "", include: "", exclude: "", activation: "", }, { group: "Doc Support", id: "crispr-guide-rna", title: "CRISPR Guide RNA", searchURL: "", typeAheadURL: "", include: "", exclude: "", activation: "", }, ]; let chosenResultsLi = []; for (i = 0; i < array1.length; i++) { if (array1[i].group === null) { chosenResultsLi.push( `<li class="active-result" data-option-array-index=${i}>${array1[i].title}</li>` ); } else { chosenResultsLi.push( `<li class="group-result" data-option-array-index=${i}>${array1[i].group}</li> <li class="active-result group-option" data-option-array-index=${i}>${array1[i].title}</li> ` ); } } let html = ""; if (chosenResultsLi.length > 0) { for (let i = 0; i < chosenResultsLi?.length; i++) { html += chosenResultsLi[i]; } focusAreaSelector.classList.add("chosen-container-active", "chosen-with-drop"); } chosenResultsUl[0].innerHTML = html;
解决方案
核心思路是先将数组按group分组,再遍历分组后的结构生成HTML,确保每个组名只输出一次。修改后的代码如下:
let chosenResultsUl = document.getElementsByClassName("chosen-results"); const array1 = [ // 原数组内容保持不变 { group: null, id: "all-categories", title: "Search All", searchURL: "", typeAheadURL: "", include: null, exclude: null, activation: null }, { group: null, id: "trial-catalog", title: "Aspire Free Products", searchURL: "", typeAheadURL: "", include: null, exclude: null, activation: "" }, { group: "Popular Product Areas", id: "taqman-assays", title: "TaqMan Assays", searchURL: "", typeAheadURL: "", include: null, exclude: "", activation: "" }, { group: "Popular Product Areas", id: "gene-exp-assays", title: "Gene Expression", searchURL: "", typeAheadURL: "", include: "", exclude: "", activation: "" }, { group: "Popular Product Areas", id: "microbe-abr-detection", title: "Microbe & ABR Detection", searchURL: "", typeAheadURL: "", include: "", exclude: "", activation: null }, { group: "Doc Support", id: "microbe-detection", title: "Microbe Detection", searchURL: "", typeAheadURL: "", include: "", exclude: "", activation: "" }, { group: "Doc Support", id: "antibiotic-resistance", title: "Antibiotic Resistance", searchURL: "", typeAheadURL: "", include: "", exclude: "", activation: "" }, { group: "Doc Support", id: "crispr-guide-rna", title: "CRISPR Guide RNA", searchURL: "", typeAheadURL: "", include: "", exclude: "", activation: "" }, ]; // 1. 按group分组数据,无组项统一归到"ungrouped"键下 const groupedData = {}; array1.forEach((item, index) => { const groupKey = item.group ?? "ungrouped"; if (!groupedData[groupKey]) { groupedData[groupKey] = []; } groupedData[groupKey].push({ ...item, index }); // 保留原索引用于data属性 }); // 2. 生成HTML内容 let html = ""; // 先处理无组的项 if (groupedData["ungrouped"]) { groupedData["ungrouped"].forEach(item => { html += `<li class="active-result" data-option-array-index=${item.index}>${item.title}</li>`; }); delete groupedData["ungrouped"]; // 处理完后移除,避免重复遍历 } // 处理带组的项:先输出组名,再输出组内所有子项 Object.entries(groupedData).forEach(([groupName, items]) => { html += `<li class="group-result" data-option-array-index=${items[0].index}>${groupName}</li>`; items.forEach(item => { html += `<li class="active-result group-option" data-option-array-index=${item.index}>${item.title}</li>`; }); }); // 3. 渲染到页面 if (html) { focusAreaSelector.classList.add("chosen-container-active", "chosen-with-drop"); } chosenResultsUl[0].innerHTML = html;
代码说明
- 分组处理:用
groupedData对象将原数组按group归类,无组项统一放到"ungrouped"键下,确保同组项被聚合在一起 - 无组项渲染:单独遍历无组项,直接生成普通
<li>元素 - 带组项渲染:遍历每个组,先输出一次组名
<li>,再依次输出该组下的所有子项<li>,保证组名仅显示一次 - 保留原索引:分组时保留原数组的索引,确保
data-option-array-index属性值与原代码一致,不影响其他依赖该属性的逻辑
内容的提问来源于stack exchange,提问作者Sanjay Tiwari
相关产品推荐
相关产品推荐

