2010-08-03 19 views
72

I reading about document fragments und DOM Reflow war und fragte sich, wie document.createDocumentFragment von document.createElement unterschied, da es wie im DOM existieren keiner von ihnen sieht, bis ich sie zu einem DOM-Element anhängen.Sollte ich document.createDocumentFragment oder document.createElement

Ich habe einen Test (unten) und alle von ihnen dauerte genau die gleiche Zeit (ca. 95ms). Vermutlich könnte das daran liegen, dass auf keines der Elemente ein Style angewendet wird, also möglicherweise kein Reflow.

Wie auch immer, basierend auf dem folgenden Beispiel, warum sollte ich createDocumentFragment anstelle von createElement beim Einfügen in das DOM verwenden und was ist der Unterschied zwischen den beiden.

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

Das klingt wie ein Job für jsperf. Ja? Nein? – Nenotlep

Antwort

75

Der Unterschied ist, dass ein Dokumentfragment effektiv verschwindet, wenn Sie es dem DOM hinzufügen. In diesem Fall werden alle untergeordneten Knoten des Dokumentfragments an der Position im DOM eingefügt, an der Sie das Dokumentfragment einfügen, und das Dokumentfragment selbst wird nicht eingefügt. Das Fragment selbst existiert weiter, hat aber keine Kinder mehr.

Auf diese Weise können Sie mehrere Knoten in das DOM zugleich einzufügen:

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

Danke für die Antwort. Sie sagen, dass es gleichzeitig mehrere Einfügungen erlaubt, aber das kann ich mit doc.createElement erreichen. Der einzige Unterschied war, dass ich die Elemente zuerst in ein -Tag verpacken und dann das in das DOM einfügen musste. Soll ich deshalb createDocumentFragment verwenden? Um zu vermeiden, dass unnötige Elemente in das DOM eingefügt werden? – screenm0nkey

+3

Ja, das ist definitiv ein Grund, es zu benutzen. Außerdem kann ein Dokumentfragment irgendeine Art von Knoten enthalten, während ein Element dies nicht tun kann. –

+3

Eigentlich "verschwindet" das Fragment nicht; Der Browser verschiebt die childNodes in das DOM. Das Fragment wird also weiterhin existieren, aber es wird nach dem Einfügen leer sein. – inf3rno

4

Ein weiterer sehr wichtiger Unterschied zwischen der Erstellung des Elements und ein Dokumentfragment:

Wenn Sie ein Element erstellen und anhängen es an das DOM, das Element wird an das DOM, sowie die Kinder angefügt.

Bei einem Dokumentfragment werden nur die untergeordneten Elemente angehängt.

Nehmen wir den Fall:

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>

, die in diesem ungültige HTML-Ergebnisse (Leerzeichen hinzugefügt)

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