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


97

我正在阅读有关文档片段和DOM重排的信息,想知道它们与DOM中不存在什么document.createDocumentFragment区别,document.createElement直到我将它们附加到DOM元素上为止。

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

无论如何,基于下面的示例,为什么在插入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');

Answers:


98

区别在于,将文档片段添加到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

3
感谢您的回复。您说它允许同时进行多个插入,但是我可以使用doc.createElement来实现。唯一的区别是我必须先将元素包装在<span>标记中,然后将该<span>插入到DOM中。这就是为什么我应该使用createDocumentFragment吗?为了避免将不必要的元素插入DOM?
screenm0nkey 2010年

4
是的,这绝对是使用它的原因之一。同样,文档片段可以包含任何种类的节点,而元素可以不包含。
Tim Down'8

3
实际上,该片段不会“消失”。浏览器将其childNodes移至DOM。因此该片段将仍然存在,但是插入后将为空。
inf3rno 2014年

1
@ inf3rno:因此,我使用“有效”一词及其后的解释,与您的解释大致相同。我承认我应该在答案中明确指出该片段继续存在而没有任何子节点。
蒂姆·唐

1
@TimDown感谢您的回答!如果我的观点正确,那么在性能,使用createFragmentcreateElement内存方面,它们都会批量更新DOM,而不是多次迭代更新,效果大致相同。这样做的主要好处createFragment是,它为您提供了自由选择要附加的子元素的灵活性吗?如果我错了,请纠正我。
Xlee

9

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

创建元素并将其附加到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>
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.