2011/03/10

Optimización de javascript (V). Repintado y reflow

Las tareas de repintado y reflow pueden hacer también que la UI no sea suficientemente ágil ya que pueden tardar mucho en realizarse si no se hacen inteligentemente.

Los cambios en la apariencia de elementos, como por ejemplo el color, fuerzan repintados y los cambios en la estructura (layout) fuerzan el reflow de los elementos de la página.
Siempre se realizan reflows cuando:
  • Se hace la carga inicial de la página
  • Se redimensiona la ventana del navegador
  • Se añaden o eliminan nodos del DOM
  • Se aplican estilos de layout
  • Se obtiene información de layout
Los repintados y reflows se encolan mientras se ejecuta el javascript para pasar a ser efectivos una vez se termina la ejecución, realizándose los cambios uno tras otro en orden. De esta manera si en un bucle se hacer 10 operaciones que fuercen un reflow, ese reflow se ejecutará 10 veces una vez termine de ejecutarse el código!.

Para evitar demasiadas ejecuciones de repintado y reflow, se pueden usar las siguientes técnicas.
Realizar manipulaciones del DOM fuera del documento

La ventaja es que mientras se manupulan los objetos fuera del documento, no se fuerzan ni repintados ni reflows. Las principales técnicas son:
  • Quitar elemento del documento, hacer las manipulaciones en el elemento, reinyectarlo en el documento.
  • Poner su propiedad de display a none, hacer los cambios, poner display de nuevo al valor original.
  • Realizar los cambios en un DocumentFragment y luego aplicarlas todas de golpe al añadir el fragmento al realizar el appendChild().
Técnica de DocumentFragment
Toda la composición se realiza fuera del documento por lo que no hay cambios hasta que se aplica.
// Ejemplo de DocumentFragment
var list = document.GetElementByClassName("items")[0],
   fragment = document.createDocumentFragment(),
   i, item;
for(i=0; i < 10; i++) {
        item = document.createElement("li");
        item.innerHTML = “Elemento #” + i;
        fragment.appendChild(item);
}
list.appendChild(fragment); // En este momento se lanza el reflow
Técnica de agrupación de los cambios de estilo
Si se cambian las propiedades de estilo de una en una, cada cambio puede dar lugar a un repintado o un reflow. Para evitarlo, se puede prediseñar la apriencia final en una clase CSS y luego en el código cambiar el className de modo que todos los cambios se hacen una única vez.
elemento.className = "estiloFinal";
También se puede hacer accediendo a la propiedad cssText
elemento.style.cssText = "color:red;height:100px;"; // un único reflow
Técnica de evitación de reflows accidentales
Cuando se consultan propiedades de layout, se fuerzan reflows (p.e. offsetWidth). Por ello se recomienda:
  • Minimizar el acceso a la información de layout
    • offsetTop, offsetLeft, offsetWidth, offsetHeight
    • scrollTop, scrollLeft, scrollWidth, scrollHeight
    • clientTop, clientLeft, clientWidth, clientHeight
    • La mayoría de los estilos calculados
  • Si un valor se usa más de una vez, almacenarlo en una variable local

    No hay comentarios:

    Publicar un comentario