在本教程中,您将了解在 DOM 树中创建新元素时 innerHTMLcreateElement 之间的区别。

createElement 性能更好

假设您有一个 div 并且类名是 container 的元素:

<div class="container"></div>

您可以通过创建元素并使用  appendChilddiv 元素添加新的子元素:

let div = document.querySelector('.container');

let p = document.createElement('p');
p.textContent = 'JS DOM';
div.appendChild(p);

您还可以像这样直接操作 HTML 元素的使用 innerHTML

let div = document.querySelector('.container');
div.innerHTML += '<p>JS DOM</p>';

当您想向元素添加属性时,使用 innerHTML 会使代码更少,更加简洁:

let div = document.querySelector('.container');
div.innerHTML += '<p class="note">JS DOM</p>';

但是,使用 innerHTML 会导致 Web 浏览器重新解析并重新创建 div 元素内的所有 DOM 节点。因此,它比创建一个新元素并追加到 div 的效率要低。

换句话说,创建一个新元素并将其追加到 DOM 树可提供比 innerHTML 更好的性能。

createElement 更安全

正如 innerHTML 教程中提到的,只有当数据来自受信任的来源(例如数据库)时才应该使用它。

如果将自己无法控制的内容赋值给元素的 innerHTML 属性,恶意代码可能会被注入并执行。

DocumentFragment 组合 DOM 节点

假设您有一个 HTML 列表,并且你需要迭代所有元素,下面的代码会导致每次迭代重新计算样式、绘制和布局,性能效率低下。

let div = document.querySelector('.container');

for (let i = 0; i < 1000; i++) {
   let p = document.createElement('p');
   p.textContent = `Paragraph ${i}`;
   div.appendChild(p);
}

为了克服这个问题,您应该使用 DocumentFragment 来组成 DOM 节点并将其追加到 DOM 树:

let div = document.querySelector('.container');

// compose DOM nodes
let fragment = document.createDocumentFragment();
for (let i = 0; i < 1000; i++) {
   let p = document.createElement('p');
   p.textContent = `Paragraph ${i}`;
   fragment.appendChild(p);
}

// append the fragment to the DOM tree
div.appendChild(fragment);

在此示例中,我们使用 DocumentFragment 对象组合 DOM 节点,并在最后将片段追加到活动 DOM 树中。

DocumentFragment 文档片段不会链接到活动 DOM 树,因此不会产生任何性能的损失。你可以查看 DocumentFragment 教程了解更多详细信息。