2011-01-19 9 views
7

En Firefox, Estoy insertando texto en ~ 500 DIVs utilizando este código:¿Cómo mejorar el rendimiento de insertar texto en un elemento HTML?

$(".divs").text("default"); // ~500 DIVs 

En mi computadora, esto toma constantemente 9 mssi los DIVs están vacías. Sin embargo, este mismo código toma consistentemente 18mssi los DIV ya contienen texto.

¿Por qué un DIV vacío es 2 veces más rápido al insertar texto? (¿Necesita jQuery primero vaciar el DIV)? Y, ¿hay alguna forma de mejorar el rendimiento de reemplazar texto en un DIV que ya contiene texto?

Nota: En IE 7, las diferencias de velocidad no fueron tan espectaculares. Insertar texto en un DIV vacío era aproximadamente 1.5 veces más rápido.

+3

¿Está buscando una diferencia de rendimiento de 9 ms? Y es evidente, si * realmente * quieres que sea rápido, lo harías con el antiguo JS. Las bibliotecas facilitan el desarrollo, pero rara vez ofrecen aumentos de rendimiento sobre el uso del código de vanilla. – ken

+4

Sí. Estoy persiguiendo una diferencia de rendimiento de 2x. –

+6

Como ejercicio académico, creo que esta es una buena pregunta, pero para su caso de uso, creo que ya ha pasado el punto de disminución de los rendimientos. Ningún usuario podrá notar una diferencia de 9 ms; para el caso, ningún usuario podría notar una diferencia de 90 ms. – ken

Respuesta

6

Si desea que la solución más rápida para todos los navegadores utilizan textContent si es compatible y vuelve a los innerText/innerHTML lo contrario [Test] (conociendo la gotchas).

/** 
* Replaces text for all elements in the given array. 
* @param {Array} elems 
* @param {String} text 
*/ 
var replaceText = (function(){ 
    var dummy = document.createElement("div"); 
    dummy.innerHTML = "text"; 
    var TEXT = (dummy.textContent === 'text') ? 'textContent' : 'innerText'; 
    return function(elems, text) { 
    for (var i = elems.length; i--;) { 
     elems[i][TEXT] = text; 
    } 
    }; 
})(); 

más rápido de jQuery texto:

  • 4x en IE 8
  • 2.2x en Firefox 4B11
  • 1.3x en Chrome
+0

Guau, ¡muy bien! –

+0

Puede aceptar la respuesta si resolvió su problema :) – galambalazs

1

Si no necesita escaparse de las etiquetas html (es decir, reemplazando <a> con &lt;a&gt;), entonces .html podría ser más rápido. También sí, necesita vaciar los divs antes de reemplazarlos con el nuevo contenido.

6

Si el texto que está insertando hace NO necesita ser escapado, entonces es posible que desee probar el siguiente:

$(".div").each(function(){ 
    this.innerHTML = "default"; 
}); 

jQuery hace algún tipo de procesamiento de texto cuando se utiliza el method .text().

Tenemos que ser conscientes de que este método escapa la cadena proporciona como necesaria para que se rinda correctamente en HTML. Para hacerlo, llama al el método DOM .createTextNode(), que reemplaza los caracteres especiales con sus equivalentes de entidad HTML (como < para <).

Editar para evitar la pena del método .each() puede probar lo siguiente:

var divs = $(".divs"), 
    i = 0, 
    len = divs.length; 
while(len--) { 
    divs[len].innerHTML = "default"; 
} 

Si eso no le consigue las ganancias de rendimiento, entonces es definitivamente un problema de implementación navegador. Al menos eso descartaría los problemas/errores de rendimiento de jQuery.

+0

Gracias por la ayuda. 1) Esto en realidad lleva más tiempo debido al bucle .each() y 2) El código es aún más rápido cuando los DIV están vacíos. –

+0

¡Podría ser un problema de implementación del navegador! usted sabe tener que liberar la memoria de esas cuerdas. Solo una suposición. ¿Has probado diferentes navegadores? –

+0

revise mi solución editada –

3

Sí, la razón de que este método es más lento cuando los elementos tienen elementos secundarios es porque el método de jQuery .text() primero se ejecuta el método .empty() y luego .append(document.createTextNode(text))

De jQuery.text

// ... 
return this.empty().append((this[0] && this[0].ownerDocument || document).createTextNode(text)); 
// ... 

La razón por la que Estoy señalando esto es que el método .empty() llama al método .cleanData() que elimina los datos y/o eventos asociados con sus nodos secundarios, y luego, hace un método estándar .removeChild() en todos sus nodos secundarios para eliminarlos, que es el razón principal por la cual los divs que ya contienen texto son más lentos de actualizar.

La solución a su problema es escribir sus propias funciones, vainilla, javaScript para actualizar el texto de sus divs, pero asegúrese de no adjuntar ningún evento o dato de clic a través de jQuery, ya que lo hará Definitivamente tienen algunas pérdidas de memoria.

3

Puede obtener rendimiento reutilizando un nodo de texto existente.

Un elemento DIV que solo contiene texto, es un elemento DOM que contiene un nodo secundario cuyo tipo es un nodo de texto. El contenido de texto se almacena dentro de este nodo de texto, y no dentro de su elemento DIV padre.

El principal problema con métodos tales como .text() en JQuery, o .innerHTML() en HTML DOM, o incluso .innerText() y .textContent(), es que todos ellos crean un nuevo nodo texto (incluso si ya existe) Más específicamente, todos los métodos enumerados anteriormente comienzan eliminando todos los nodos hijo DOM, incluido un nodo de texto eventualmente preexistente (esto también lo hacen las implementaciones de innerHTML, innerText y textContent). Esto deja el elemento de contexto (el DIV, en su caso) vacío, sin ningún hijo en absoluto. A continuación, crean un nuevo nodo secundario del tipo nodo de texto, asignándole el nuevo texto y anexándolo al elemento de contexto. innerHTML además intenta analizar la cadena HTML de entrada y construye un fragmento DOM fuera de ella.

El método más rápido que yo sepa para la sustitución de un nodo de texto actual es el siguiente:

var divs = $(".divs").get(), 
    len = divs.length; 
while(--len) { 
    divs[len].firstChild.data = "default"; 
} 

Este método no crea un nuevo nodo secundario, sino que simplemente reemplaza el texto del nodo de texto existente. Obviamente, este método supone que el nodo de texto ya existe. Para que esto funcione, su documento inicial se puede inicializar con cualquier texto no vacío dentro de los DIV (y excluyendo cualquier otro elemento secundario).

Cuestiones relacionadas