开发者问题收集

将 document.createElement('div') 更改为 document.createDocumentFragment()

2021-04-14
283
const allItemContainer = document.getElementById("all-items");
data.pizza.forEach((item) => {
        let container = document.createElement("div");
        //container will contain <div class='shop-item'>
        container.classList.add("shop-item");
        container.id = item.id; //will add an id to the current div equal to the ID given in the json file
        let textHeading = document.createElement("span");
        textHeading.classList.add("shop-item-title");
        textHeading.appendChild(document.createTextNode(item.name));
}
container.appendChild(textHeading);
allItemContainer.appendChild(container);
});

我希望将 document.createElement() 更改为 document.createDocumentFragment() 。我尝试更改它,但出现错误:- 未捕获(在承诺中)TypeError:无法读取未定义的属性“add” 如何将 classList 添加到此 Fragment?我是新手。请帮忙。

2个回答

由于 DocumentFragments 不是 HTML 元素,因此您无法在其上添加类。它就像一个用于向其附加子项的容器。它位于内存中,不是 DOM 树的一部分。因此,当您在 DocumentFragments 上附加子项时,它不会改变 DOM 树的流程。将元素附加到文档片段,然后将文档片段附加到 DOM 树。

In the DOM tree, the document fragment is replaced by all its children. MDN

根据 MDN

DocumentFragments are DOM Node objects which are never part of the main DOM tree. The usual use case is to create the document fragment, append elements to the document fragment and then append the document fragment to the DOM tree. In the DOM tree, the document fragment is replaced by all its children.

const data = {
  pizza: [{
      id: "100",
      name: "pizza1"
    },
    {
      id: "101",
      name: "pizza2"
    },
    {
      id: "102",
      name: "pizza3"
    },
    {
      id: "103",
      name: "pizza4"
    },
  ],
};

const allItemContainer = document.getElementById("all-items");
const fragment = document.createDocumentFragment();

data.pizza.forEach((item) => {
  let container = document.createElement("div");
  //container will contain <div class='shop-item'>
  container.classList.add("shop-item");
  container.id = item.id; //will add an id to the current div equal to the ID given in the json file
  let textHeading = document.createElement("span");
  textHeading.classList.add("shop-item-title");
  textHeading.appendChild(document.createTextNode(item.name));
  container.appendChild(textHeading);
  fragment.appendChild(container);
});

allItemContainer.appendChild(fragment);
.shop-item {
  padding: .5rem;
  color: white;
  background-color: gray;
}
<div id="all-items"></div>
DecPK
2021-04-14

Due to performance reasons, I wanted to shift to fragment

您的代码无效,但我假设 allItemContainer.appendChild(container); 调用位于 forEach 回调中。如果是这样,并且添加这些元素确实会导致性能问题,那么您可以通过将每个容器添加到片段并在末尾插入片段来改进这一点,从而只导致一次重排(而不是为每个容器触发一次重排):

const allItemContainer = document.createDocumentFragement();

data.pizza.forEach((item) => {
    let container = document.createElement("div");
    //container will contain <div class='shop-item'>
    container.classList.add("shop-item");
    container.id = item.id; //will add an id to the current div equal to the ID given in the json file
    let textHeading = document.createElement("span");
    textHeading.classList.add("shop-item-title");
    textHeading.appendChild(document.createTextNode(item.name));
    container.appendChild(textHeading);
    allItemContainer.appendChild(container);
});

document.getElementById("all-items").appendChild(allItemContainer);
Felix Kling
2021-04-14