¿Debo usar document.createDocumentFragment o document.createElement


97

Estaba leyendo sobre fragmentos de documentos y reflujo de DOM y me preguntaba en qué se document.createDocumentFragmentdiferenciaba, document.createElementya que parece que ninguno de ellos existe en el DOM hasta que los agrego a un elemento DOM.

Hice una prueba (a continuación) y todas tomaron exactamente la misma cantidad de tiempo (aproximadamente 95 ms). Supongo que esto podría deberse a que no se ha aplicado un estilo a ninguno de los elementos, por lo que tal vez no haya reflujo.

De todos modos, según el ejemplo a continuación, ¿por qué debería usarlo en createDocumentFragmentlugar de createElemental insertarlo 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');

Respuestas:


98

La diferencia es que un fragmento de documento desaparece efectivamente 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 en sí no se inserta. El fragmento en sí sigue 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. Dices que permite múltiples inserciones al mismo tiempo, pero puedo lograrlo usando doc.createElement. La única diferencia es que primero tuve que envolver los elementos en una etiqueta <span> y luego insertar ese <span> en el DOM. ¿Es por eso que debería usar createDocumentFragment? ¿Para evitar que se inserten elementos innecesarios en el DOM?
screenm0nkey

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

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

1
@ inf3rno: De ahí mi uso de la palabra "efectivamente" y la explicación que sigue, que es muy parecida a la suya. Admito que debería haber dicho explícitamente en la respuesta que el fragmento continúa existiendo sin nodos secundarios.
Tim Down

1
@TimDown ¡gracias por tu respuesta! Si entiendo bien su punto, con respecto al rendimiento, el uso createFragmenty la createElementmemoria tienen aproximadamente el mismo efecto, ya que ambos actualizaron el DOM por lotes en lugar de actualizarlo iterativamente varias veces. Si bien el principal beneficio createFragmentes que le ofrece la flexibilidad de elegir los elementos secundarios que desee agregar de forma gratuita. Corrígeme si me equivoco.
Xlee

9

Otra diferencia muy importante entre crear un elemento y un fragmento de documento:

Cuando crea un elemento y lo agrega al DOM, el elemento se agrega al DOM, así como a los elementos secundarios.

Con un fragmento de documento, solo se agregan los niños.

Toma 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 da como resultado este HTML con formato incorrecto (espacio en blanco agregado)

<ul id="ul_test">
  <li>Document Fragment</li>
  <div><li>Inside Div</li></div>
</ul>
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.