2010-08-03 11 views
72

Sono stato reading about document fragments e DOM reflow e mi sono chiesto come lo document.createDocumentFragment differisse da document.createElement poiché sembra che nessuno di essi esista nel DOM finché non li aggiungo a un elemento DOM.Devo utilizzare document.createDocumentFragment o document.createElement

Ho eseguito un test (di seguito) e tutti hanno richiesto esattamente lo stesso tempo (circa 95ms). Ad una ipotesi questo potrebbe essere dovuto al fatto che non ci sono stili applicati a nessuno degli elementi, quindi nessun reflow può essere.

In ogni caso, in base all'esempio seguente, perché dovrei utilizzare createDocumentFragment invece di createElement quando si inserisce nel DOM e quale è la differenza tra i due.

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

Questo suona come un lavoro per jsperf. Sì? No? – Nenotlep

risposta

75

La differenza è che un frammento di documento scompare efficacemente quando lo aggiungi al DOM. Quello che succede è che tutti i nodi figli del frammento del documento sono inseriti nella posizione nel DOM in cui si inserisce il frammento del documento e il frammento del documento stesso non è inserito. Il frammento stesso continua ad esistere ma ora non ha figli.

Questo consente di inserire più nodi nel DOM al tempo stesso:

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

Grazie per la risposta. Dici che consente più inserimenti contemporaneamente, ma posso farlo utilizzando doc.createElement. L'unica differenza è che ho dovuto prima avvolgere gli elementi in un tag e quindi inserire quello nel DOM. È per questo che dovrei usare createDocumentFragment? Per evitare che elementi inutili vengano inseriti nel DOM? – screenm0nkey

+3

Sì, questo è sicuramente uno dei motivi per usarlo. Inoltre, un frammento di documento può contenere qualsiasi tipo di nodo mentre un elemento non può. –

+3

In realtà il frammento non "scompare"; il browser sposta i suoi childNodes nel DOM. Quindi il frammento esisterà ancora, ma sarà vuoto dopo l'inserimento. – inf3rno

4

Un'altra importante differenza tra la creazione di un elemento e un frammento di documento:

Quando si crea un elemento e aggiungere al DOM, l'elemento viene aggiunto al DOM e ai bambini.

Con un frammento di documento, vengono aggiunti solo i bambini.

Prendiamo il caso di:

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>

che si traduce in questo HTML malformato (spazio bianco aggiunto)

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