¿Por qué "element.innerHTML+=" es un código incorrecto?
Me han dicho que no agregue cosas element.innerHTML += ...
de esta manera:
var str = "<div>hello world</div>";
var elm = document.getElementById("targetID");
elm.innerHTML += str; //not a good idea?
¿Qué tiene de malo?, ¿qué otras alternativas tengo?
Cada vez que innerHTML
se configura, se debe analizar el HTML, construir un DOM e insertarlo en el documento. Esto lleva tiempo.
Por ejemplo, si elm.innerHTML
tiene miles de divs, tablas, listas, imágenes, etc., la llamada .innerHTML += ...
hará que el analizador vuelva a analizar todo eso nuevamente. Esto también podría romper las referencias a elementos DOM ya construidos y provocar otro caos. En realidad, todo lo que desea hacer es agregar un elemento nuevo al final.
Es mejor simplemente llamar appendChild
:
var newElement = document.createElement('div');
newElement.innerHTML = '<div>Hello World!</div>';
elm.appendChild(newElement);
De esta manera, el contenido existente de elm
no se vuelve a analizar.
NOTA: Es posible que [algunos] navegadores sean lo suficientemente inteligentes como para optimizar el +=
operador y no volver a analizar los contenidos existentes. No he investigado esto.
Sí, elm.innerHTML += str;
es una muy mala idea.
Úselo elm.insertAdjacentHTML( 'beforeend', str )
como la alternativa perfecta.
La típica respuesta "el navegador tiene que reconstruir el DOM" realmente no hace justicia a la pregunta:
Primero, el navegador debe revisar cada elemento de elm, cada una de sus propiedades y todos sus textos, comentarios y nodos de proceso, y escapar de ellos para crear una cadena.
Luego tienes una cadena larga, a la que agregas. Este paso está bien.
En tercer lugar, cuando configuras internalHTML, el navegador tiene que eliminar todos los elementos, propiedades y nodos por los que acaba de pasar.
Luego analiza la cadena, la construye a partir de todos los elementos, propiedades y nodos que acaba de destruir, para crear un nuevo fragmento DOM que es prácticamente idéntico.
Finalmente, adjunta los nuevos nodos y el navegador tiene que diseñar todo. Esto puede evitarse (consulte la alternativa a continuación), pero incluso si los nodos agregados requieren un diseño, los nodos antiguos tendrían sus propiedades de diseño almacenadas en caché en lugar de volver a calcularse desde cero.
¡Pero aún no ha terminado! El navegador también tiene que reciclar nodos antiguos escaneando todas las variables de JavaScript.
Problemas:
Es posible que HTML no refleje algunas propiedades; por ejemplo, el valor actual de
<input>
se perderá y se restablecerá al valor inicial en HTML.Si tiene controladores de eventos en los nodos antiguos, se destruirán y deberá volver a conectarlos todos.
Si su código js hace referencia a nodos antiguos, no se destruirán, sino que quedarán huérfanos. Pertenecen al documento pero ya no están en el árbol DOM. Cuando su código acceda a ellos, es posible que no suceda nada o que se produzca un error.
Ambos problemas significan que no es compatible con los complementos js: los complementos pueden adjuntar controladores o mantener referencias a nodos antiguos y provocar una pérdida de memoria.
Si adquiere el hábito de manipular DOM con InnerHTML, puede cambiar propiedades accidentalmente o hacer otras cosas que no deseaba.
Cuantos más nodos tenga, más ineficiente será y más energía tendrá la batería para nada.
En resumen, es ineficiente, propenso a errores, simplemente es vago y desinformado.
La mejor alternativa esElement.insertAdjacentHTML
que no he visto otras respuestas mencionar:
elm.insertAdjacentHTML( 'beforeend', str )
Casi el mismo código, sin los problemas de InnerHTML. Sin reconstrucción, sin pérdida de controlador, sin reinicio de entrada, menos fragmentación de memoria, sin malos hábitos, sin creaciones y asignaciones manuales de elementos.
Le permite inyectar cadenas html en elementos en una línea, incluidas propiedades, e incluso le permite inyectar elementos compuestos y múltiples. Su velocidad está optimizada : en la prueba de Mozilla es 150 veces más rápida.
En caso de que alguien le diga que no es compatible con varios navegadores, es tan útil que es el estándar HTML5 y está disponible en todos los navegadores .
No vuelvas a escribir nunca
elm.innerHTML+=
más.