在JavaScript中附加多个项目

bru*_*odd 20 html javascript appendchild

我有以下功能,我试图找出一个更好的方法来使用附加多个项目appendChild().

当用户点击"添加"时,每个项目应如下所示:

<li>
  <input type="checkbox">
  <label>Content typed by the user</label>
  <input type="text">
  <button class="edit">Edit</button>
  <button class="delete">Delete</button>
</li>
Run Code Online (Sandbox Code Playgroud)

我有这个功能来添加这些元素:

function addNewItem(listElement, itemInput) {
  var listItem = document.createElement("li");
  var listItemCheckbox = document.createElement("input");
  var listItemLabel = document.createElement("label");
  var editableInput = document.createElement("input");
  var editButton = document.createElement("button");
  var deleteButton = document.createElement("button");

  // define types
  listItemCheckbox.type = "checkbox";
  editableInput.type = "text";

  // define content and class for buttons
  editButton.innerText = "Edit";
  editButton.className = "edit";
  deleteButton.innerText = "Delete";
  deleteButton.className = "delete";

  listItemLabel.innerText = itemText.value;

  // appendChild() - append these items to the li
  listElement.appendChild(listItem);
  listItem.appendChild(listItemCheckbox);
  listItem.appendChild(listItemLabel);
  listItem.appendChild(editButton);
  listItem.appendChild(deleteButton);

  if (itemText.value.length > 0) {
    itemText.value = "";
    inputFocus(itemText);
  }
}
Run Code Online (Sandbox Code Playgroud)

但是你可以看到,我重复三次appendChild()listItem.是否可以添加多个项目appendChild()

小智 50

您可以使用DocumentFragment完成此操作.

var documentFragment = document.createDocumentFragment();
documentFragment.appendChild(listItem);
listItem.appendChild(listItemCheckbox);
listItem.appendChild(listItemLabel);
listItem.appendChild(editButton);
listItem.appendChild(deleteButton);
listElement.appendChild(documentFragment);
Run Code Online (Sandbox Code Playgroud)

DocumentFragments允许开发人员将子元素放置在类似任意节点的父节点上,从而允许类似节点的交互,而无需真正的根节点.这样做允许开发人员在可见DOM内生成结构而不这样做

  • 但是这些`appendChild`调用都不会发生在实时DOM中,因此浏览器不会尝试在追加每个子节点后重新呈现整个DOM.相反,在附加整个片段之后,仅发生一次重新渲染. (6认同)
  • 这应该是接受的答案,因为它使用DOM API而不是字符串.非常酷的回答.谢谢. (4认同)
  • 很棒的答案 - DocumentFragment是一种非常有用的方法,可以将更改批处理到渲染的DOM. (2认同)
  • mozilla 文档:[Document.createDocumentFragment()](https://developer.mozilla.org/en-US/docs/Web/API/Document/createDocumentFragment) (2认同)

Sag*_*r V 21

您可以在JavaScript中使用append方法.

这与jQuery的append方法类似,但它不支持IE和Edge.

您可以更改此代码

listElement.appendChild(listItem);
listItem.appendChild(listItemCheckbox);
listItem.appendChild(listItemLabel);
listItem.appendChild(editButton);
listItem.appendChild(deleteButton);
Run Code Online (Sandbox Code Playgroud)

listElement.append(listItem,listItemCheckbox,listItemLabel,editButton,deleteButton);
Run Code Online (Sandbox Code Playgroud)

  • @skzryzg 我认为我从“mdn”中看到的不再是实验性的。 (4认同)

小智 13

合并@Atrahasis 和@Slavik 的答案:

\n\n
if (Node.prototype.appendChildren === undefined) {\n  Node.prototype.appendChildren = function() {\n    let children = [...arguments];\n\n    if (\n      children.length == 1 &&\n      Object.prototype.toString.call(children[0]) === "[object Array]"\n    ) {\n      children = children[0];\n    }\n\n    const documentFragment = document.createDocumentFragment();\n    children.forEach(c => documentFragment.appendChild(c));\n    this.appendChild(documentFragment);\n  };\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

这接受子项作为多个参数,或作为单个数组参数:

\n\n
foo.appendChildren(bar1, bar2, bar3);\nbar.appendChildren([bar1, bar2, bar3]);\n
Run Code Online (Sandbox Code Playgroud)\n\n
\n\n

更新 \xe2\x80\x93 2020 年 6 月

\n\n

现在大多数当前的浏览器都支持append扩展运算符”

\n\n

上面的调用可以重写为:

\n\n
foo.append(bar1, bar2, bar3);\nbar.append(...[bar1, bar2, bar3]);\n
Run Code Online (Sandbox Code Playgroud)\n


Mar*_*cki 7

让我们试试这个:

let parentNode = document.createElement('div');

parentNode.append(...[
    document.createElement('div'),
    document.createElement('div'),
    document.createElement('div'),
    document.createElement('div'),
    document.createElement('div')
]);

console.log(parentNode);
Run Code Online (Sandbox Code Playgroud)


cнŝ*_*ŝdk 6

就个人而言,我不明白您为什么要这么做。

但如果你真的需要更换所有appendChild()有一个说法,您可将outerHTML创建的元素到innerHTML了的li元素。

您只需要替换以下内容:

  listElement.appendChild(listItem);
  listItem.appendChild(listItemCheckbox);
  listItem.appendChild(listItemLabel);
  listItem.appendChild(editButton);
  listItem.appendChild(deleteButton);
Run Code Online (Sandbox Code Playgroud)

具有以下内容:

listItem.innerHTML+= listItemCheckbox.outerHTML + listItemLabel.outerHTML + editButton.outerHTML + deleteButton.outerHTML;
listElement.appendChild(listItem);
Run Code Online (Sandbox Code Playgroud)

说明:

元素DOM接口的externalHTML属性获取描述元素(包括其后代)的序列化HTML片段。所以分配outerHTML的创建的元素到innerHTML了的li元素类似于他们追加到它。

  • 这实际上并没有附加子项,而是附加了它们的副本,这会丢失属性。 (2认同)
  • 设置一个属性,如`listCheckbox.asdf = 5; listItem.innerHTML = listCheckbox.outerHTML; listItem.querySelector('input').asdf === 5` 它将为 false,因为在 externalHTML 中找不到属性(与属性不同)。对于输入项,丢失的最重要的属性是“.value”(与属性“value”不同)。还有事件侦听器等。对于许多目的(包括此处),您的解决方案可以工作,但它确实会丢失属性并且速度要慢得多。 (2认同)

Atr*_*sis 5

您需要追加几个孩子吗?只需将其变为复数即可appendChildren

首先要做的事情是:

HTMLLIElement.prototype.appendChildren = function () {

  for ( var i = 0 ; i < arguments.length ; i++ )

    this.appendChild( arguments[ i ] );

};
Run Code Online (Sandbox Code Playgroud)

然后对于任何列表元素:

listElement.appendChildren( a, b, c, ... );

//check :
listElement.childNodes;//a, b, c, ...
Run Code Online (Sandbox Code Playgroud)

当然,适用于具有appendChild方法的每个元素!喜欢HTMLDivElement

  • @RockinSocks 将一系列节点附加到片段,并且仅在所有内容放在一起后才附加片段,避免了浏览器必须对页面上元素的位置和大小进行多次重新计算,即进行多次回流。这样,当您将片段附加到实时 DOM 时,回流只会发生一次。因此,更改应该呈现得更快。请参阅此处的快速说明 - https://www.sitepoint.com/10-ways-minimize-reflows-improve-performance/。 (2认同)

asd*_*dru 5

您可以使用 createContextualFragment,它返回从字符串创建的 documentFragment。如果您必须构建多个并将其附加Node到现有的Element所有内容中,那么它是完美的,因为您可以将其全部添加,而不会出现以下缺点:innerHTML

https://developer.mozilla.org/en-US/docs/Web/API/Range/createContextualFragment

// ...
var listItem = document.createElement("li");
var documentFragment = document.createRange().createContextualFragment(`
    <input type="checkbox">
    <label>Content typed by the user</label>
    <input type="text">
    <button class="edit">Edit</button>
    <button class="delete">Delete</button>
`)
listItem.appendChild(documentFragment)
// ...
Run Code Online (Sandbox Code Playgroud)