2010-09-21 28 views
13

Tengo una aplicación web en la que estaríamos insertando cientos de elementos en el DOMmejor manera de insertar cientos de elementos DOM en la página dinámicamente mientras se mantiene un alto rendimiento de

Esencialmente, estoy haciendo

$('#some_element').html('<lots of html here>'); 

repetidamente. En algunos casos podría necesitar hacer $('#some_element').appendTo('more html');

De experiencia previa al insertar texto html usando el apéndice o configurando el innerHTML de un elemento es lento.

He oído que puede aumentar el rendimiento colocando primero los elementos en un fragmento DOM y luego moviendo su ubicación al interior del elemento que desea.

El rendimiento de esto es la clave. ¿Tienen algún consejo o sugerencia para maximizar el rendimiento? ¿Algún truco que pueda hacer para que esto sea rápido?

Editar: como se menciona en un comentario: La aplicación implica un flujo en tiempo real de varios datos, por lo que debe ser capaz de agregar constantemente nuevos elementos DOM para representar los nuevos datos. (Esto también podría conducir a otro problema de tener demasiados elementos DOM, por lo que necesitaría elementos que son demasiado viejos).

+3

Teniendo en cuenta los requisitos, su enfoque actual parece razonable. ¿Se siente lento actualmente? –

+0

Sí, hay un pequeño retraso cuando el navegador representa el nuevo html. Por lo tanto, el navegador se siente congelado de 300 ms a 600 ms. Pero como hay más datos, no quiero ese aumento, que es lo que me preocupa. – rksprst

+1

¿Puedes proporcionar una página web de muestra? –

Respuesta

11

Simplemente no hagas html() (o usa su primo natal innerHTML = …) varias veces. Empaque su HTML en una variable y haga html() solo una vez (o las veces que sea posible). Ej .:

var buf = [], i = 0; 

buf[i++] = "<p>";    /* or use buf.push(string) */ 
buf[i++] = "some text"; 
buf[i++] = "some other text"; 
buf[i++] = "</p>"; 

element.innerHTML = buf.join(""); 

Véase también la Quirksmode entry on innerHTML y la página W3C DOM vs. innerHTML.

Actualización: Ayer encontré la sorprendente artículo When innerHTML isn't Fast Enough por Steven Levithan sobre su función replaceHtml, que es incluso más rápido que utilizando sólo innerHTML, ya que elimina los nodos DOM que van a ser reemplazados mediante la manipulación DOM estándar antesinnerHTML se utiliza:

function replaceHtml(el, html) { 
    var oldEl = typeof el === "string" ? document.getElementById(el) : el; 
    /*@cc_on // Pure innerHTML is slightly faster in IE 
     oldEl.innerHTML = html; 
     return oldEl; 
    @*/ 
    var newEl = oldEl.cloneNode(false); 
    newEl.innerHTML = html; 
    oldEl.parentNode.replaceChild(newEl, oldEl); 
    /* Since we just removed the old element from the DOM, return a reference 
    to the new element, which can be used to restore variable references. */ 
    return newEl; 
}; 
+0

La aplicación implica un flujo en tiempo real de varios datos, por lo que debe ser capaz de agregar constantemente nuevos elementos DOM. – rksprst

+0

@rksprst: pero si lo hace de una vez, no se dará cuenta, ya que la ejecución del script bloquea la redención. "[F] primero poner los elementos en un fragmento DOM y luego mover su ubicación al interior del elemento" es en realidad lo que estoy mostrando. No hay forma más rápida, al menos hasta donde yo sé. –

+0

Gracias por la ayuda, bastante tarde en la pista, solo un consejo para los demás: descubrí que tenía que agregar var buf = [], i = 0; para que mi código funcione – dpmguise

0

transmisión en tiempo real debe actualización no anexar. Como se mencionó, use un buffer. Otra cosa que podrías hacer es.

var buffer = []; 
setInterval(function(){ $("#div").html(buffer.join(""); buffer = []; }, 1000); 

buffer.push("html"); 
buffer.push("html"); 

Establezca el tiempo de espera para lo que necesite y vaciará el búfer y lo adjuntará.

Aquí hay una función e intervalo que puede usar.

var buffer = []; 
var wait = 1000; /* ms to wait, 1000 = 1 second */ 
var htmlId = "puthere"; /* Change this to the div ID */ 

setInterval(function(){ 
    var tmp = buffer; /* Switch the buffer out quickly so we aren't scrambled 
         if you addToBuffer in the middle of this */ 
    buffer = []; 
    document.getElementById(htmlId).innerHTML = tmp.join(""); 
}, wait); 

addToBuffer = function(html){ 
    buffer.push(html); 
}; 
+1

La concurrencia de JS no funciona de esa manera; no puede ser programado "en el medio de esto". – raylu

+0

@raylu Buen punto, gracias. Esta respuesta es anterior a una gran parte de mi experiencia JS. –

1

para aclarar lo que dijo Marcel en su respuesta:

manipulación del DOM (usando appendTo, la creación de elementos de, textNode de, etc) es órdenes de magnitud más lento que acaba de leer/escribir innerHTML.

Cuestiones relacionadas