You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何生成带唯一组名的独立<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;

代码说明
  1. 分组处理:用groupedData对象将原数组按group归类,无组项统一放到"ungrouped"键下,确保同组项被聚合在一起
  2. 无组项渲染:单独遍历无组项,直接生成普通<li>元素
  3. 带组项渲染:遍历每个组,先输出一次组名<li>,再依次输出该组下的所有子项<li>,保证组名仅显示一次
  4. 保留原索引:分组时保留原数组的索引,确保data-option-array-index属性值与原代码一致,不影响其他依赖该属性的逻辑

内容的提问来源于stack exchange,提问作者Sanjay Tiwari

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 11:25:18