Document.createDocumentFragment veya document.createElement kullanmalı mıyım


97

Ben edildi belge parçaları hakkında okuma ve DOM yeniden akıtma ve nasıl merak document.createDocumentFragmentfarklıydı document.createElementben bir DOM öğesine bunları eklemek kadar ikisi de DOM var gibi görünüyor gibi.

Bir test yaptım (aşağıda) ve hepsi tam olarak aynı süreyi aldı (yaklaşık 95 ms). Tahminen bu, muhtemelen öğelerin hiçbirine stil uygulanmamış olmasından kaynaklanıyor olabilir, bu nedenle yeniden düzenleme olmayabilir.

Her neyse, aşağıdaki örneğe göre , DOM'a eklerken neden createDocumentFragmentyerine kullanmalıyım createElementve ikisi arasındaki fark nedir?

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');

Yanıtlar:


99

Aradaki fark, bir belge parçasını DOM'a eklediğinizde etkili bir şekilde kaybolmasıdır. Olan şey, belge parçasının tüm alt düğümlerinin, belge parçasını eklediğiniz DOM'daki konuma eklenmesi ve belge parçasının kendisinin eklenmemesidir. Parçanın kendisi var olmaya devam ediyor ama şimdi çocuğu yok.

Bu, DOM'a aynı anda birden fazla düğüm eklemenize olanak tanır:

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
Cevabınız için teşekkürler. Aynı anda birden fazla eklemeye izin verdiğini söylüyorsunuz, ancak bunu doc.createElement kullanarak başarabilirim. Tek fark, öğeleri önce bir <span> etiketine sarmam ve ardından bu <span> öğesini DOM'a eklemem gerekti. Bu yüzden mi createDocumentFragment kullanmalıyım? DOM'a gereksiz öğelerin eklenmesini önlemek için?
screenm0nkey

4
Evet, kesinlikle kullanmak için bir neden. Ayrıca, bir belge parçası herhangi bir tür düğüm içerebilirken bir öğe olmayabilir.
Tim Down

3
Aslında parça "kaybolmaz"; tarayıcı, childNode'larını DOM'a taşır. Dolayısıyla parça hala var olacak, ancak yerleştirildikten sonra boş olacak.
inf3rno

2
@ inf3rno: Dolayısıyla "etkili" kelimesini kullanıyorum ve aşağıdaki açıklama, sizinkiyle hemen hemen aynı. Yanıtta, parçanın alt düğümler olmadan var olmaya devam ettiğini açıkça söylemem gerektiğini kabul ediyorum.
Tim Down

1
Cevabınız için @TimDown teşekkürler! Puanınızı doğru anlarsam, performans, kullanım createFragmentve createElementbellekle ilgili olarak, her ikisi de birden çok kez yinelemeli olarak güncelleme yapmak yerine DOM'u toplu olarak güncelledikleri için kabaca aynı etkiye sahiptir . Temel faydası , size hangi alt unsurları ücretsiz olarak ekleyebileceğinizi seçme esnekliği sunmasıdır. Hatalıysam düzeltin. createFragment
Xlee

9

Bir öğe ve bir belge parçası oluşturmak arasındaki çok önemli bir fark:

Bir öğe oluşturduğunuzda ve bunu DOM'a eklediğinizde, öğe hem DOM'a hem de alt öğelere eklenir.

Bir belge parçasıyla, yalnızca alt öğeler eklenir.

Şu durumu ele alalım:

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>

bu hatalı biçimlendirilmiş HTML'ye (boşluk eklendi) neden olur

<ul id="ul_test">
  <li>Document Fragment</li>
  <div><li>Inside Div</li></div>
</ul>
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.