是否有更好的方法来整理一系列对象来动态生成按值分开的HTML元素



我正在通过一系列对象循环,以动态生成HTML,由对象中的一个或多个值排序。

数据:

data = [ { value: "FirstValue", category: "FirstCategory" }, { value: "SecondValue", category: "FirstCategory" }, { value: "ThirdValue", category: "SecondCategory" }, { value: "FourthValue", category: "FirstCategory" }]

我的解决方案首先创建一个空数组,通过数据中的对象迭代,检查类别数组是否包含对象类别。

如果类别中的类别,我发现具有类别值的HTML,请在内部附加必要的值。

如果类别不在类别中,我将新类别推到类别数组中,创建一个新的HTML DIV,内部具有类别值,并附加一个HTML DIV,并在该新创建的类别div中带有对象值。

categories = [];
for (var i = 0; i < data.length; i++) {
    value = data[i][value]
    category = data[i][category];
    if (categories.includes(category)) {
        console.log("Category already in array");
        existingCatBlock = findHTMLWhereCatIsCat(category);
        newHTMLBlockWithValue = newBlock(value);
        existingCatBlock.append(newHTMLBlockWithValue);
    } 
    else {
        categories.push(category);
        newCategoryBlock = newBlockWithCat(category);
        newHTMLBlockWithValue = newBlock(value);
        newCategoryBlock.append(newHTMLBlockWithValue);
        mainHTMLContainer.append(newCategoryBlock);
    }
}

当前的解决方案可以完成工作,但是也许有更好,更优雅的已知方法可以做到这一点,尤其是在情况下,还有更多的价值。

主要是为了可读性,我将尝试先操纵数组,以您想要的方式对其进行排序,然后在屏幕上添加所有内容。

我将首先从您的数据中创建一个字典,其键将是类别,并且值将是带有类别值的数组。Array.reduce()可用于构建它。这给出以下对象:

{
  "FirstCategory": [
    "FirstValue",
    "SecondValue",
    "FourthValue"
  ],
  "SecondCategory": [
    "ThirdValue"
  ]
}

然后,您可以使用Object.entries()Array.forEach()Array.map()在本字典的条目上迭代该字典的条目,以构建每个类别,添加其子女并将整个类别插入DOM。

这样,您不必跟踪DOM中已经存在的哪些类别。您只需要与所有孩子一起插入一次,这要归功于将类别的中间映射到值。

const data = [
  { value: "FirstValue", category: "FirstCategory" },
  { value: "SecondValue", category: "FirstCategory" },
  { value: "ThirdValue", category: "SecondCategory" },
  { value: "FourthValue", category: "FirstCategory" }
];
const dataByCategories = data.reduce((acc, { value, category }) => {
  acc[category] = [...(acc[category] || []), value];
  return acc;
}, {});
const mainHTMLContainer = document.querySelector('#main');
Object.entries(dataByCategories).forEach(([category, values]) => {
  const valuesHTML = values.map(newBlock).join('');
  const categoryBlock = newBlockWithCat(category, valuesHTML);
  // A single appendChild is done for each category
  mainHTMLContainer.appendChild(categoryBlock);
});
function newBlock(value) {
  return `<div class="value">html for ${value}</div>`;
}
function newBlockWithCat(category, values) {
  const div = document.createElement('div');
  div.classList.add('category');
  div.innerHTML = values;
  return div;
}
.value {
  padding: 2px;
}
.category {
  display: inline-block;
  border: 1px solid black;
  width: 150px;
  margin: 5px;
}
<div id="main">
</div>

最新更新