¿Por qué la operación DOM en JavaScript es tan lenta?
En el navegador, la implementación de DOM y JS no utiliza la misma "cosa". Por ejemplo, el motor JS con el que estamos más familiarizados en Chrome es V8, y DOM y el renderizado se basan en la biblioteca WebCore. En otras palabras, DOM y JS son dos entidades independientes. Piense en DOM y JavaScript como islas, conectadas por puentes de peaje.
--"JavaScript de alto rendimiento" 1. Agregue elementos de página, método internalHTML?vs?DOM. document.getElementById('test').innerHTML='lt;divgt;testlt;/divgt;';
var?t=document.createElement('div');
t.appendChild(document.createTextNode('test'));
document.getElementById('test').appendChild(t);
Lo anterior utiliza dos métodos respectivamente. un div al elemento con id='test'. Antes, es posible que todo el mundo haya sido adoctrinado con la idea de que el HTML interno es más rápido. ¿Es este realmente el caso?
Eso es cierto, al menos en IE, pero en los nuevos navegadores basados en webkit, usar el método DOM será un poco más rápido. Por lo tanto, qué método utilizar debería seguir siendo algo controvertido. Personalmente me gusta InnerHTML porque es más fácil de usar.
Además, cuando es necesario agregar una gran cantidad de elementos idénticos, cloneNode es un poco más rápido que crear elementos directamente. 2. La forma correcta de acceder a los elementos.
2.1. Atravesar colecciones versus atravesar matrices
Cuando usamos document.getElementsByName, document.getElementsByTagName, document.getElementsByClassName, docuemnt.images, etc. para obtener elementos DOM, obtenemos Es una colección HTML. Esta colección siempre está conectada al documento subyacente. Cada vez que obtenga la información de la colección, se ejecutará una consulta repetidamente. var?divs=document.getElementByTagName('div');
for(var?i=0;ilt;divs.length;i){ document.body.append(document.createElement('div' ))?
}
Si no lo ejecutamos, podemos pensar que el código anterior agregará varios elementos div nuevos a la página, pero de hecho, porque cada vez uno Si se agrega div, divs.length se actualizará (incrementará en uno), por lo que este ciclo nunca se detendrá. La solución es muy simple var?divs=document.getElementByTagName('div');
for(var?i=0,len=divs.length;ilt;len;i){ document.body. append (document.createElement('div'))?
}
Además, la colección HTML no es una matriz. Si necesitamos recorrer esta colección, primero podemos copiar. en una matriz, de modo que cuando lo atraviese nuevamente, será más eficiente.
function?toArray(coll){ for(var?i=0, a=[], len=coll.length; ilt; len; i ){ a[i]=coll[i]?
} return?a;?
}
2.2. Acceder a los atributos del elemento
Al atravesar una colección, el atributo de longitud debe almacenarse en caché fuera del bucle para evitar la lógica. error en 2.1; almacenar colecciones en variables locales también puede mejorar la eficiencia. Además, al acceder a atributos del mismo elemento DOM, almacenar en caché el DOM en una variable local es una mejor opción. //Solo como demostración, por supuesto, no existe tal requisito en situaciones reales
//La peor manera
function?fo1(){
var? nombre=''; for(var?i=0;ilt;document.getElementsByTagName('div');i){
nombre=document.getElementsByTagName('div').nodeName;
name=document.getElementsByTagName('div').nodeType;
}? return?name;?
}
//Mejor manera
función?fo2(){
var?name='';
var?coll=document.getElementsByTagName('div');
for(var?i=0, len=coll.length; ilt; len; i ){ nombre=coll[i].nodeName; nombre=coll[i].nodeType;
}
return?name;
}
//Mejor manera
function?fo3(){ var? var?coll=document.getElementsByTagName('div'); var?ele=null; for(var?i=0, len=coll.length; ilt; len; i ){
el= coll[i]; name=el.nodeName; name=el.nodeType;?
}
} 3. Selector
Delante Se ha mencionado que document.getElementsByName, document.getElementsByTagName, document.getElementsByClassName, docuemnt.images y otros métodos obtienen una colección HTML, lo cual es ineficiente en comparación con querySelector y querySelectorAll, lo que se obtiene es una NodeList, que es un objeto tipo Array no; causar problemas con las colecciones HTML. Además, esta API es más conveniente a la hora de obtener elementos. La única pregunta es si el navegador de destino lo admite. 4. Redibujar y reorganizar
4.1 ¿Cuándo redibujar y reorganizar?
Redibujar no necesariamente conduce a redibujar. Por ejemplo, cambiar el color de un elemento solo provocará un redibujo y, después del redibujo, el navegador debe volver a dibujar las partes afectadas por el redibujo.
Los motivos para la reorganización incluyen:
Agregar o eliminar elementos DOM
Cambios en la posición, el tamaño y el contenido de los elementos
Cambios en el tamaño de la ventana del navegador
Aparece la barra de desplazamiento
Debido a que las operaciones de reordenar y volver a dibujar son muy costosas, el navegador las optimizará poniendo en cola las modificaciones y ejecutándolas en lotes (tengo entendido que el navegador realizará la optimización mediante colas y lotes). ejecución, reduciendo el número de redibujados). Por ejemplo: //Este código no se volverá a dibujar tres veces
var?bodyStyle=document.body.style;
bodyStyle.color='red';
bodyStyle.color='black';
bodyStyle.color='green';
La operación de obtención del diseño hará que la cola se actualice y la optimización del navegador El efecto también se verá afectado. No hay más. Para evitar obtener las siguientes propiedades cuando cambia la información del diseño:
offsetTop, offsetLeft, offsetWidth, offsetHeight
scrollTop, scrollLeft, scrollWidth, scrollHeight;
clientTop; , clientLeft, clientWidth, clientHeight;
getComputedStyle()/currentStyle
4.2 Sugerencias para minimizar la reorganización y el rediseño
Sugerencia: no modificar el diseño nuevamente. Al recibir información, consulte la información de diseño var?computed;
var?tmp='';
var?bodyStyle=document.body.style;
si (document.body.currentStyle){ computed=document.body.currentStyle?
}else{ computed=document.defaultView.getComputedStyle(document.body, '')
}
//malo
bodyStyle.color='rojo';
tmp=computed.backgroundColor;
bodyStyle.color=' verde ';
tmp=computed.backgroundImage;
//bueno
bodyStyle.color='rojo';
bodyStyle color. ='green';
tmp=computed.backgroundColor;
tmp=computed.backgroundImage;
Cuando modifiques varios estilos de un elemento, hazlo a la vez Modifique, no varias veces (aunque las modificaciones múltiples, después de la optimización de los navegadores modernos, solo causarán un reflujo, en los navegadores antiguos, aún causarán múltiples reflujos). Sugerencia: si se puede resolver usando clases CSS, intente no usar estilos en línea.
: el desplazamiento ralentizará la velocidad de respuesta. Evite usarlo cuando trabaje con listas grandes. 5. Delegación de eventos
Cada vez que vinculas un controlador de eventos, hay un precio. Si hay una gran cantidad de elementos que deben vincularse en un momento determinado, intente utilizar la delegación de eventos.
Tres pasos
Determinar el origen del evento
Realizar diferentes operaciones según las diferentes fuentes
Cancelar la propagación y evitar el comportamiento predeterminado (opcional) document.querySelector(' #nav').onclick=función?(e)?{
if?(e.target.nodeName=='A'){
foo();
}else{
foo2()
}
}
Resumen:
Reducir Número de visitas al DOM
Si accede al mismo DOM varias veces, debe utilizar variables locales para almacenar en caché el DOM
Utilice querySelector tanto como sea posible en lugar de utilizar la API para obtener el Colección HTML
Preste atención al redistribución y redibujado
Utilice la delegación de eventos para reducir el número de eventos vinculados
Para obtener más información, puede leer "JavaScript de alto rendimiento "
El contenido anterior de:?cnblogs, www.cnblogs.com/yepbug/p/5427213.html