我应该使用 document.createDocumentFragment 还是 document.createElement

IT技术 javascript dom
2021-02-20 23:23:30

我正在阅读有关文档片段和 DOM 重排的内容,并想知道它们有何document.createDocumentFragment不同,document.createElement因为在我将它们附加到 DOM 元素之前,它们似乎都不存在于 DOM 中。

我做了一个测试(如下),所有这些都花费了完全相同的时间(大约 95 毫秒)。猜测这可能是由于没有应用于任何元素的样式,因此可能没有回流。

无论如何,基于下面的示例,为什么我应该在插入 DOM 时使用createDocumentFragment而不是使用它createElement以及两者之间的区别是什么。

var htmz = "<ul>";
for (var i = 0; i < 2001; i++) {
    htmz += '<li><a href="#">link ' + i + '</a></li>';
}
htmz += '<ul>';

//createDocumentFragment
console.time('first');
var div = document.createElement("div");
div.innerHTML = htmz;
var fragment = document.createDocumentFragment();
while (div.firstChild) {
    fragment.appendChild(div.firstChild);
}
$('#first').append(fragment);
console.timeEnd('first');

//createElement
console.time('second');
var span = document.createElement("span");
span.innerHTML = htmz;
$('#second').append(span);
console.timeEnd('second');


//jQuery
console.time('third');
$('#third').append(htmz);
console.timeEnd('third');
2个回答

不同之处在于,当您将文档片段添加到 DOM 时,它会有效地消失。发生的情况是文档片段的所有子节点都插入到 DOM 中您插入文档片段的位置,而文档片段本身并未插入。片段本身继续存在,但现在没有孩子。

这允许您同时将多个节点插入 DOM:

var frag = document.createDocumentFragment();
var textNode = frag.appendChild(document.createTextNode("Some text"));
var br = frag.appendChild(document.createElement("br"));
var body = document.body;
body.appendChild(frag);
alert(body.lastChild.tagName); // "BR"
alert(body.lastChild.previousSibling.data); // "Some text"
alert(frag.hasChildNodes()); // false
@TimDown 感谢您的回答!如果我的观点是正确的,关于性能、使用createFragmentcreateElement内存的效果大致相同,因为它们都是批量更新 DOM 而不是迭代更新多次。虽然 的主要好处createFragment是它让您可以灵活地选择要免费附加的任何子元素?如果我错了,请纠正我。
2021-04-16 23:23:30
实际上片段并没有“消失”;浏览器将其子节点移动到 DOM。所以片段仍然存在,但插入后它将为空。
2021-04-19 23:23:30
感谢您的回复。您说它允许同时进行多个插入,但我可以使用 doc.createElement 实现这一点。唯一的区别是我必须先将元素包装在 <span> 标签中,然后将该 <span> 插入到 DOM 中。这就是我应该使用 createDocumentFragment 的原因吗?避免将不必要的元素插入到 DOM 中?
2021-04-25 23:23:30
@inf3rno:因此,我使用了“有效地”一词以及随后的解释,这与您的解释大致相同。我承认我应该在答案中明确指出片段继续存在,没有子节点。
2021-05-12 23:23:30
是的,这绝对是使用它的原因之一。此外,文档片段可能包含任何类型的节点,而元素可能不包含。
2021-05-15 23:23:30

创建元素和文档片段之间的另一个非常重要的区别:

当您创建一个元素并将其附加到 DOM 时,该元素将附加到 DOM 以及子元素。

对于文档片段,仅附加子项。

以以下案例为例:

var ul = document.getElementById("ul_test");


// First. add a document fragment:


(function() {
  var frag = document.createDocumentFragment();
  
  
  var li = document.createElement("li");
  li.appendChild(document.createTextNode("Document Fragment"));
  frag.appendChild(li);
  
  ul.appendChild(frag);
  console.log(2);
}());

(function() {
  var div = document.createElement("div");
  
  
  var li = document.createElement("li");
  li.appendChild(document.createTextNode("Inside Div"));
   div.appendChild(li);
  
  ul.appendChild(div);
}());
Sample List:
<ul id="ul_test"></ul>

这导致这种格式错误的 HTML(添加了空格)

<ul id="ul_test">
  <li>Document Fragment</li>
  <div><li>Inside Div</li></div>
</ul>