Descargo de responsabilidadParece que estoy comenzando una nueva serie de artículos, un poco aburrida y puramente utilitaria. Explicarán los puntos que a menudo causan dificultades a mis alumnos. Si eres un desarrollador web experimentado, lo más probable es que no te interese. Si estás esperando perversiones en el poder del JS del viernes, no estarán aquí, por desgracia.
Una de las cosas que los estudiantes regularmente tienen problemas para entender es DocumentFragment. En general, no puedo culparlos. Con simplicidad externa, tiene varias propiedades no evidentes e incluso contraintuitivas. En este artículo quiero recopilar todo lo que un principiante necesita saber sobre él.

Que es esto
Un DocumentFragment es un contenedor que puede contener un número arbitrario de elementos DOM. Si simplemente, puedes imaginarlo como un cubo. Los elementos se apilan en él para que en el momento adecuado se puedan descargar de inmediato.
Cómo crear
Elemental
var fragment = document.createDocumentFragment();
También hay otras formas, pero sobre ellas a continuación.
Porque necesito
Como escribí anteriormente, para almacenar elementos DOM. "Pero pueden almacenarse en una diva ordinaria", puede objetar el lector. Es cierto, sin embargo, que el fragmento tiene una propiedad única que lo convierte en el mejor candidato para este papel. Considere el siguiente código:
var fragment = document.createDocumentFragment(); var parentDiv = document.createElement("div"); var div1 = document.createElement("div"); var div2 = document.createElement("div"); fragment.appendChild(div1); fragment.appendChild(div2);
¿Qué nos dirá la consola? Una persona que no
parentDiv
familiarizada con DocumentFragment podría pensar que
parentDiv
tendrá un
fragment
secundario. Pero, de hecho, tendrá dos hijos:
div1
y
div2
. El hecho es que el fragmento en sí no es un elemento DOM, es solo un contenedor para elementos DOM. Y cuando se pasa como argumento a métodos como
appendChild
o
insertBefore
, no se incrusta en el árbol DOM, sino que incrusta su contenido allí.
¿Pero por qué lo necesitas?
La propiedad "cubo" es, por supuesto, buena, pero ¿cómo es esto útil en la práctica? DocumentFragment tiene dos áreas principales de aplicación.
1. Almacenar piezas de HTML que no tienen un ancestro común.Hay situaciones en las que necesitamos reemplazar el contenido de un elemento, pero no tocamos el elemento en sí. Supongamos que usamos delegación de eventos, y todos los controladores de eventos que ocurren en elementos internos se cuelgan en un div externo. En este caso, DocumentFragment es ideal para nosotros:
div.innerHTML = ""; div.appendChild(fragmentWithAllContent);
"¿Pero podemos agregar elementos al div de inmediato a medida que los creamos?" - preguntará el lector corrosivo. Podemos, pero no vale la pena, y por eso.
2. Mejora del rendimiento en el caso de múltiples insertos.El hecho es que cada vez que cambiamos algo en el árbol DOM activo, el navegador tiene que hacer muchos cálculos. Puedes leer más sobre esto
aquí , por ejemplo. En este artículo, nos limitamos a mencionar que hay una bestia tan terrible: el reflujo. Cuando agregamos un elemento a la página, esta bestia se despierta y consume un poco de tiempo de procesador. Si agregamos cien elementos, la bestia se despertará cien veces y morderá cien veces. Para el usuario, esto puede ser un "congelamiento" bastante notable.
Cuando agregamos un elemento al DocumentFragment, esto no causa reflujo, porque el fragmento no es (y básicamente no puede ser) parte del árbol DOM activo. Y lo más importante: cuando insertamos el contenido de un fragmento usando
appendChild
u otros métodos similares, independientemente de cuántos elementos hay dentro del fragmento, el
reflujo se llama solo una vez .
Para mayor claridad, hice un
punto de referencia simple para que el lector pueda ver personalmente la diferencia.
Upd: el camarada
nuit dijo que para Chrome moderno mis palabras ya no son ciertas. En él, el reflujo no se ejecuta antes de lo necesario, y gracias a esto, el código sin DocumentFragment en realidad funciona
más rápido , y con otros navegadores no es tan obvio. Por lo tanto, antes de decidir si usar fragmentos, necesita perfiles e investigación sobre el público objetivo del sitio.
Matices
Hay dos características que hacen que los principiantes a menudo sean difíciles de usar fragmentos. Primero: como escribí anteriormente, un fragmento
no es
un elemento DOM . Esto significa que carece de muchos métodos y propiedades familiares, en particular,
innerHTML
. Por lo tanto, no puede simplemente convertir una cadena en el contenido de un fragmento. Cómo hacerlo no es fácil, se describirá a continuación.
La segunda característica: el fragmento cuando se usa "botín". Más precisamente, se vacía. Cuando hacemos
div.appendChild(fragment)
, todos los hijos del fragmento están
div.appendChild(fragment)
en un
div
. Y dado que un elemento no puede tener más de un padre, esto significa que se eliminan del fragmento. Para evitar este comportamiento cuando no es deseable, puede usar
cloneNode
.
etiqueta <template>
Hay un lugar donde puede encontrar DocumentFragment sin crearlo a través de JS. Esta es la propiedad de
content
del elemento de plantilla.
La
<template>
inventó específicamente para almacenar fragmentos de código HTML, pero no para cargar el navegador antes de tiempo. Lo que está dentro de esta etiqueta no se convierte en parte del árbol DOM activo. En particular (los recién llegados a menudo también se encuentran con esto), no se pueden encontrar usando
querySelector
. Los elementos creados a partir del código HTML dentro de la etiqueta
<template>
no se convierten en elementos secundarios. En cambio, JavaScript puede acceder a ellos a través de la propiedad de
content
, lo cual es una sorpresa. - solo DocumentFragment.
Usando el elemento de plantilla, puede crear un fragmento de una cadena:
function createFragmentFromString(str){ var template = document.createElement("template"); template.innerHTML = str; return template.content; }
Epílogo
Si eres nuevo en el desarrollo web, espero que hayas aprendido mucho. Si eres un desarrollador experimentado, es posible que desees complementar este artículo con algo, en cuyo caso no dudes en escribirlo en los comentarios. Gracias por leer y que tengas un buen día.