2008-09-22 13 views
21

Tengo este mal presentimiento acerca de cómo inserto grandes cantidades de HTML. supongamos que tenemos:jquery: inserción DOM más rápida?

var html="<table>..<a-lot-of-other-tags />..</table>"

y yo queremos poner esto en

$("#mydiv")

previamente que hice algo así como

var html_obj = $(html); $("#mydiv").append(html_obj);

¿Es correcto th en jQuery está analizando html para crear DOM-Objects? Bueno, esto es lo que he leído en alguna parte (ACTUALIZACIÓN: que quería decir que he leído, jQuery analiza el HTML para crear todo el árbol DOM con la mano - su derecho sin sentido ?! ), por lo que cambió mi código:

$("#mydiv").attr("innerHTML", $("#mydiv").attr("innerHTML") + html);

Se siente más rápido, ¿verdad? Y es correcto que esto es equivalente a:

document.getElementById("mydiv").innerHTML += html? o está jquery haciendo cosas adicionales caras en el fondo?

Me encantaría aprender alternativas también.

Respuesta

21

innerHTML es notablemente rápido, y en muchos casos obtendrá los mejores resultados simplemente estableciendo eso (yo solo usaría append).

Sin embargo, si ya hay mucho en "mydiv", está forzando al navegador a analizar y volver a mostrar todo ese contenido (todo lo que había antes, más todo su contenido nuevo). Esto se puede evitar si se añade un fragmento de documento en "mydiv" en su lugar:

var frag = document.createDocumentFragment(); 
frag.innerHTML = html; 
$("#mydiv").append(frag); 

De esta manera, sólo el nuevo contenido se analiza (inevitable) y el contenido existente no lo hace.

EDIT: Mi mal ... He descubierto que innerHTML no está bien soportado en fragmentos de documentos. Puede usar la misma técnica con cualquier tipo de nodo. Para su ejemplo, se podría crear el nodo de la tabla de la raíz y de insertar el innerHTML en que:

var frag = document.createElement('table'); 
frag.innerHTML = tableInnerHtml; 
$("#mydiv").append(frag); 
+1

Esto funcionó para mí, pero tuve que usar append(), no appendChild(). ¿Typo, o ha cambiado el nombre del método? –

+0

No estoy seguro de cómo podría haberse escapado, pero no creo que sea un método renombrado. Actualizaré mi publicación. – Prestaul

+1

appendChild() es el método w3c DOM que hace lo mismo que append() en jQuery (aprox.) – xj9

1

Para empezar, escriba una secuencia de comandos que mide el tiempo que lleva hacerlo 100 o 1,000 veces con cada método.

Para asegurarse de que las repeticiones no se optimicen de alguna manera - No soy un experto en motores de JavaScript - cambie el html que está insertando cada vez, digamos poniendo '0001' luego '0002' y luego '0003 'en una cierta celda de la mesa.

9

¿Qué intenta evitar? "Un mal presentimiento" es increíblemente vago. Si ha escuchado "el DOM es lento" y decidió "evitar el DOM", entonces esto es imposible. Cada método de inserción de código en una página, incluido innerHTML, dará como resultado la creación de objetos DOM. El DOM es la representación del documento en la memoria de su navegador. Usted quiere objetos DOM que se crearán. El motivo por el que las personas dicen "el DOM es lento" se debe a que crear elementos con document.createElement(), que es la interfaz DOM oficial para crear elementos, es más lento que usar la propiedad innerHTML no estándar en algunos navegadores. Esto no significa que crear objetos DOM es malo, es necesario para crear objetos DOM, de lo contrario su código no haría nada en absoluto.

-1

Menciona que le interesan las alternativas. Si mira el listado de DOM-related jQuery plugins, encontrará varios que están dedicados a la generación programática de árboles DOM. Ver por ejemplo SuperFlyDom o DOM Elements Creator; pero hay otros

+0

estos usarían fragmentos de DOM, ¿no es así? –

2

La respuesta sobre el uso de un fragmento DOM está en el camino correcto. Si tiene un grupo de objetos html que está insertando constantemente en el DOM, verá algunas mejoras de velocidad al usar el fragmento. Este post por John Resig lo explica muy bien: http://ejohn.org/blog/dom-documentfragments/

+0

No mencionó que quiere poner un fragmento en más de un elemento. Su pregunta indica que quiere poner un html frag en un elemento. Además, 'document fragment' se crea dentro de jQuery implícitamente. – galambalazs

32

intente lo siguiente:

$("#mydiv").append(html); 

Las otras respuestas, incluyendo la respuesta aceptada, son más lentos por 2-10x: jsperf.

La respuesta aceptada no funciona en IE 6, 7 y 8 porque no se puede establecer innerHTML de un elemento <table>, debido a un error en el IE: jsbin.

+1

+1, construyendo el html como una cadena y usando un solo 'append' en lugar de construir cada elemento usando jquery, aumentó el rendimiento en mi caso en un orden de magnitud (creó 280 divs, cada uno con una tabla y un par de filas , tomó 12 segundos, ahora está en 1.1).Aunque es posible que desee reducir los insultos ...;) – falstro

+1

+1 por publicar un enlace jsperf.com cuando eso es exactamente lo que necesita –

+0

Su prueba es deshonesta. Crea un nuevo fragmento dom para cada elemento. se supone que debes agregar todos los elementos a un fragmento dom, luego insertarlo en el árbol dom. Aquí hay una prueba REAL http://jsperf.com/scriptjunkie-premature-7 –

1

La forma más rápida para añadir elementos

La forma más rápida para anexar al árbol DOM es para amortiguar toda su anexados a un fragmento DOM sola, tiene que poner el fragmento DOM para el DOM.

Este es el método que uso en mi motor de juego.

//Returns a new Buffer object 
function Buffer() { 

    //the framgment 
    var domFragment = document.createDocumentFragment(); 

    //Adds a node to the dom fragment 
    function add(node) { 
     domFragment.appendChild(node); 
    } 

    //Flushes the buffer to a node 
    function flush(targetNode) { 

     //if the target node is not given then use the body 
     var targetNode = targetNode || document.body; 

     //append the domFragment to the target 
     targetNode.appendChild(domFragment); 

    } 

    //return the buffer 
    return { 
     "add": add, 
     "flush": flush 
    } 
} 


//to make a buffer do this 
var buffer = Buffer(); 

//to add elements to the buffer do the following 
buffer.add(someNode1); 

//continue to add elements to the buffer 
buffer.add(someNode2); 
buffer.add(someNode3); 
buffer.add(someNode4); 
buffer.add(someN...); 

//when you are done adding nodes flush the nodes to the containing div in the dom 
buffer.flush(myContainerNode); 

El uso de este objeto que soy capaz de hacer ~ 1000 elementos a la pantalla ~ 40 veces por segundo en Firefox 4.

Aquí es un caso de uso.

+0

¡Escribí ese código gracias! La pregunta es "¿cuál es la forma más rápida de anexarse ​​al dom"? El tipo está insertando una mesa. No importa si es una tabla o un div. Obviamente, no leíste muy bien mi respuesta. Y decir que la inserción perceptual es más rápida que el almacenamiento en búfer y anexar sigue siendo totalmente erróneo. Si no puede entender la relevancia que es malo para usted. –

+0

No me sorprende si lo "escribió", no hay nada mágico en eso, ni siquiera dije que está mal en sí mismo, la cuestión es que todavía no está relacionado con la pregunta. Y todavía no le da derecho a llamar a la respuesta de otra persona, a quién le importa leer la pregunta, a ser deshonesto. Eres deshonesto con el sentido común. – galambalazs

+0

¿Qué significa eso deshonesto para el sentido común? El chico quería insertar una cantidad de nodos relacionados con la mesa. Un fragmento de DOM hará esto. Parece que tienes un complejo de superioridad. –

0

Creo una cadena gigante con y luego anexar esta cadena con jquery. Funciona bien y rápido, para mí.

Cuestiones relacionadas