2010-08-03 10 views
72

Estaba reading about document fragments y DOM reflow y me preguntaba cómo document.createDocumentFragment difería de document.createElement ya que parece que ninguno de ellos existe en el DOM hasta que los anexo a un elemento DOM.Debería usar document.createDocumentFragment o document.createElement

Hice una prueba (a continuación) y todas tomaron exactamente la misma cantidad de tiempo (aproximadamente 95ms). Supongo que esto podría deberse a que no se aplica ningún estilo a ninguno de los elementos, por lo que no hay reflujo.

De todos modos, en función del ejemplo a continuación, ¿por qué debería utilizar createDocumentFragment en lugar de al insertar en el DOM y cuál es la diferencia entre los dos.

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

Esto suena como un trabajo para jsperf. ¿Sí? ¿No? – Nenotlep

Respuesta

75

La diferencia es que un fragmento de documento efectivamente desaparece cuando lo agrega al DOM. Lo que sucede es que todos los nodos secundarios del fragmento de documento se insertan en la ubicación en el DOM donde se inserta el fragmento de documento y el fragmento de documento no se inserta. El fragmento en sí continúa existiendo, pero ahora no tiene hijos.

Esto le permite insertar múltiples nodos en el DOM al mismo tiempo:

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

Gracias por la respuesta. Usted dice que permite la inserción múltiple al mismo tiempo, pero puedo lograr eso usando doc.createElement. La única diferencia es que tuve que envolver los elementos en una etiqueta primero y luego insertar ese en el DOM. ¿Es por eso que debería usar createDocumentFragment? Para evitar la inserción de elementos innecesarios en el DOM? – screenm0nkey

+3

Sí, definitivamente esa es una razón para usarlo. Además, un fragmento de documento puede contener cualquier tipo de nodo, mientras que un elemento puede no contenerlo. –

+3

En realidad, el fragmento no "desaparece"; el navegador mueve sus childNodes al DOM. Por lo tanto, el fragmento seguirá existiendo, pero estará vacío después de la inserción. – inf3rno

4

Otra diferencia muy importante entre la creación de un elemento y un fragmento de documento:

Cuando se crea un elemento y anexar al DOM, el elemento se agrega al DOM, así como a los niños.

Con un fragmento de documento, solo se añaden los elementos secundarios.

Tomemos el caso de:

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>

lo que se traduce en este incorrecto HTML (añade espacio en blanco)

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