¿Cuál es la forma más eficiente de crear elementos HTML usando jQuery?

425

Recientemente he estado haciendo muchas ventanas emergentes de ventanas modales y qué no, para lo cual usé jQuery. El método que utilicé para crear los nuevos elementos en la página ha sido abrumadoramente similar a:

$("<div></div>");

Sin embargo, tengo la sensación de que este no es el mejor ni el método más eficiente para hacerlo. ¿Cuál es la mejor manera de crear elementos en jQuery desde una perspectiva de rendimiento?

Esta respuesta tiene los puntos de referencia para las sugerencias a continuación.

Darko Z
fuente
1
Experimente también con la eliminación de estilos y vea si eso acelera las cosas. Creo que la aplicación CSS y las actualizaciones ralentizan más las cosas en las páginas grandes para mí.
CVertex
3
Tenga cuidado con la optimización prematura: si no está haciendo esto para cientos de elementos DOM a la vez, o está usando navegadores MUY antiguos, entonces probablemente no notará ninguna diferencia en el rendimiento del navegador.
Blazemonger
1
@Blazemonger No era tanto que necesitaba un método más eficiente para crear elementos DOM, pero la situación en la que me encontraba me hizo reflexionar sobre cuáles son las alternativas y cuán eficientes podrían ser.
Darko Z
2
jQuery es una biblioteca: casi siempre incurrirá en gastos generales de rendimiento por este motivo: es como hablar con alguien a través de un intérprete. A menos que desee utilizar JavaScript sin procesar, aproveche lo rápido que es escribir $ ('<div>') y acepte el impacto en el rendimiento.
Danny Bullis
1
jsben.ch/#/bgvCV <= este punto de referencia debería responder a su pregunta
EscapeNetscape

Respuestas:

307

Uso $(document.createElement('div')); Benchmarking muestra que esta técnica es la más rápida. Supongo que esto se debe a que jQuery no tiene que identificarlo como un elemento y crear el elemento en sí.

Realmente debería ejecutar puntos de referencia con diferentes motores de Javascript y sopesar su audiencia con los resultados. Toma una decisión a partir de ahí.

extraño
fuente
16
jQuery lo "agrega" al DOM? ¿Dónde? Esto no tiene mucho sentido para mí, ¿a dónde iría el div?
Strager
28
Se debe agregar un div creado en jquery al igual que en javascript. $ ('<div>') por sí solo no se adjunta al DOM hasta que lo agregue () a algo.
Owen
66
@David, obviamente tienes razón. Notaré que agregué el comentario hace aproximadamente 2 años justo cuando comenzaba a aprender jQuery. Tendría que hacer un appendTo, ... Debido a que los comentarios obviamente estaban equivocados, los eliminé.
tvanfosson
16
La referencia de evaluación comparativa es excelente, pero también está probando la creación de decenas de miles de elementos. ¿Cuándo se enfrentará a tantos elementos en una situación típica? Lo más probable es que tenga cosas más importantes de las que preocuparse que cómo crear un elemento. document.createElement "Ran 39,682 veces en 0.097 segundos", mientras que $ ('<div>') "Ran 12,642 en 0.068 segundos". Diría que si algo puede ejecutarse miles de veces en menos de un segundo, estás a salvo.
Danny Bullis
20
Además, usando $ (document.createElement ('div')); Yo diría que es menos eficiente porque lleva más tiempo escribir por la pequeña cantidad de beneficio que obtendrá en el navegador si solo está creando un elemento a la vez aquí y allá. Técnicamente, jQuery en sí mismo es menos eficiente como biblioteca debido a los costos de búsqueda y a los gastos generales en los que incurre al usarlo. Si alguien está tan decidido a ahorrar preciosas milésimas de milisegundo usando document.createElement en lugar de $ ('<div>'), entonces no debería usar jQuery:], porque $ ('<div>') es una de las razones por las que lo usas!
Danny Bullis
163

personalmente sugeriría (para facilitar la lectura):

$('<div>');

algunos números sobre las sugerencias hasta ahora (safari 3.2.1 / mac os x):

var it = 50000;

var start = new Date().getTime();
for (i = 0; i < it; ++i)  {
  // test creation of an element 
  // see below statements
}
var end = new Date().getTime();
alert( end - start );                

var e = $( document.createElement('div') );  // ~300ms
var e = $('<div>');                          // ~3100ms
var e = $('<div></div>');                    // ~3200ms
var e = $('<div/>');                         // ~3500ms              
Owen
fuente
15
De los documentos de jquery: 'Al crear elementos individuales, use la etiqueta de cierre o el formato XHTML. Por ejemplo, para crear un lapso use $ ("<span />") o $ ("<span> </span>") en lugar de sin la barra / etiqueta de cierre. '
tvanfosson el
66
@ Owen, ese comportamiento es un error, no una característica. Basura adentro, basura afuera: simplemente sucede que la basura que obtienes es aceptable. Sin embargo, no confíe en él entre las versiones de jQuery, a menos que cambie la especificación de la función.
extraño
2
Como se esperaba, se observan números similares en Mac OS X Chrome (100 ms para createElement () frente a análisis de texto de 500 ms) y Mac OS X Firefox (350 ms frente a 1000 ms). Gracias por escribir el bucle de prueba.
Annika Backstrom
3
@tvanfosson Esto aparentemente ha cambiado, en los documentos actuales dice: "Cuando el parámetro tiene una sola etiqueta (con etiqueta de cierre opcional o cierre rápido) - $ (" <img /> ") o $ (" <img> " ), $ ("<a> </a>") o $ ("<a>") - jQuery crea el elemento usando la función nativa JavaScript createElement () ".
metatron
3
@MarcStober Sin ofender. Todavía está aquí: http://api.jquery.com/jQuery/#jQuery2 . Los documentos mencionan la etiqueta de cierre opcional o cierre rápido
metatron
155

Pregunta:

¿Cuál es la forma más eficiente de crear elementos HTML usando jQuery?

Responder:

Como se trata de jQueryeso, creo que es mejor usar este enfoque (limpio) (que está usando)

$('<div/>', {
    'id':'myDiv',
    'class':'myClass',
    'text':'Text Only',
}).on('click', function(){
    alert(this.id); // myDiv
}).appendTo('body');

MANIFESTACIÓN.

De esta manera, incluso puede usar controladores de eventos para el elemento específico como

$('<div/>', {
    'id':'myDiv',
    'class':'myClass',
    'style':'cursor:pointer;font-weight:bold;',
    'html':'<span>For HTML</span>',
    'click':function(){ alert(this.id) },
    'mouseenter':function(){ $(this).css('color', 'red'); },
    'mouseleave':function(){ $(this).css('color', 'black'); }
}).appendTo('body');

MANIFESTACIÓN.

Pero cuando se trata de muchos elementos dinámicos, debe evitar agregar eventos handlersen un elemento en particular, en su lugar, debe usar un controlador de eventos delegado, como

$(document).on('click', '.myClass', function(){
    alert(this.innerHTML);
});

var i=1;
for(;i<=200;i++){
    $('<div/>', {
        'class':'myClass',
        'html':'<span>Element'+i+'</span>'
    }).appendTo('body');
}

MANIFESTACIÓN.

Por lo tanto, si crea y agrega cientos de elementos con la misma clase, es decir ( myClass), se consumirá menos memoria para el manejo de eventos, ya que solo un controlador estará allí para hacer el trabajo para todos los elementos insertados dinámicamente.

Actualización: ya que podemos usar el siguiente enfoque para crear un elemento dinámico

$('<input/>', {
    'type': 'Text',
    'value':'Some Text',
    'size': '30'
}).appendTo("body");

Pero el sizeatributo no puede establecerse usando este enfoque usando jQuery-1.8.0o más tarde y aquí hay un informe de error antiguo , mire este ejemplo usando jQuery-1.7.2que muestra que el sizeatributo está configurado para 30usar el ejemplo anterior pero usando el mismo enfoque que no podemos establecer sizeusando el atributo jQuery-1.8.3, aquí es un violín que no funciona . Entonces, para establecer elsize atributo, podemos usar el siguiente enfoque

$('<input/>', {
    'type': 'Text',
    'value':'Some Text',
    attr: { size: "30" }
}).appendTo("body");

O este

$('<input/>', {
    'type': 'Text',
    'value':'Some Text',
    prop: { size: "30" }
}).appendTo("body");

Podemos pasar attr/propcomo un objeto hijo, pero funciona en jQuery-1.8.0 and laterversiones, consulte este ejemplo pero no funcionará en jQuery-1.7.2 or earlier(no probado en todas las versiones anteriores).

Por cierto, tomado del jQueryinforme de error

Hay varias soluciones Lo primero es no usarlo en absoluto, ya que no le ahorra espacio y esto mejora la claridad del código:

Aconsejaron utilizar el siguiente enfoque ( funciona también en los anteriores , probado en 1.6.4)

$('<input/>')
.attr( { type:'text', size:50, autofocus:1 } )
.val("Some text").appendTo("body");

Entonces, es mejor usar este enfoque, OMI. Esta actualización se realiza después de leer / encontrar esta respuesta y en esta respuesta muestra que si usa en 'Size'(capital S)lugar de 'size'eso, funcionará bien , incluso enversion-2.0.2

$('<input>', {
    'type' : 'text',
    'Size' : '50', // size won't work
    'autofocus' : 'true'
}).appendTo('body');

Lea también sobre el accesorio , porque hay una diferencia, Attributes vs. Propertiesvaría según las versiones.

El alfa
fuente
¿Qué tipo de sintaxis es este $ ('<div />', {.........}), lo busqué y encontré algunos similares usando $ ('<div>) .attr ( {......})?
Rafael Ruiz Tabares
@RafaelRuizTabares, al $('<div>', {...})pasar un objeto que contiene todos los atributos y al $('<div>').attr({...})crear un elemento sin ningún atributo, pero estableciendo los atributos utilizando el attr()método más adelante.
The Alpha
@TheAlpha, ¿dónde puedo encontrar información sobre lo que puedo escribir dentro de {}? Porque veo que son atributos y eventos, pero para <div> también usa html. ¡Gracias!
Rafael Ruiz Tabares
El jQuery.comsitio web de búsqueda podría ser útil @RafaelRuizTabares, o búscalo en Google :-)
The Alpha
2
¡Esta es, con mucho, la forma más limpia y legible! Probablemente no sea la forma rápida, pero ciertamente menos errores propensos a la adición de cadenas. Gracias @TheAlpha
Ares
37

En realidad, si lo estás haciendo $('<div>'), jQuery también usarádocument.createElement() .

(Solo eche un vistazo a la línea 117 ).

Hay cierta sobrecarga de llamadas a funciones, pero a menos que el rendimiento sea crítico (está creando cientos [miles] de elementos), no hay muchas razones para volver a DOM simple .

Simplemente crear elementos para una nueva página web es probablemente un caso en el que mejor se adhiera a la forma jQuery de hacer las cosas.

edwin
fuente
20

Si tiene una gran cantidad de contenido HTML (más que un solo div), puede considerar construir el HTML en la página dentro de un contenedor oculto, luego actualizarlo y hacerlo visible cuando sea necesario. De esta forma, una gran parte de su marcado puede ser analizado previamente por el navegador y evitar que JavaScript se atasque cuando se lo llama. ¡Espero que esto ayude!

Collin Allen
fuente
Gracias por el consejo. He usado este enfoque antes, sin embargo, en este caso particular, quiero saber específicamente sobre la creación de elementos.
Darko Z
20

Esta no es la respuesta correcta para la pregunta, pero aún así me gustaría compartir esto ...

Usar solo document.createElement('div')y omitir JQuery mejorará mucho el rendimiento cuando quieras crear muchos elementos sobre la marcha y agregarlos a DOM.

Irshad
fuente
16

Creo que está utilizando el mejor método, aunque podría optimizarlo para:

 $("<div/>");
tvanfosson
fuente
11

No necesita un rendimiento bruto de una operación que realizará con muy poca frecuencia desde el punto de vista de la CPU.

Yfeldblum
fuente
Depende de con qué frecuencia lo esté haciendo.
Rich Bradshaw
8
El OP está creando una ventana emergente modal . Esta operación no se repite miles de veces por segundo. En cambio, se repite tal vez una vez cada pocos segundos, como máximo. Usar el jQuery(html :: String)método está perfectamente bien. A menos que la situación sea extremadamente inusual, es poco probable que se logre un mejor rendimiento percibido . Gasta la energía de optimización en los casos que podrían usarlo. Además, jQuery está optimizado para la velocidad de muchas maneras. Haga cosas sensatas con él y confíe, pero verifique que sea rápido.
yfeldblum
9

Tendrá que comprender que la importancia del rendimiento de creación de elementos es irrelevante en el contexto del uso de jQuery en primer lugar.

Tenga en cuenta que no hay un propósito real de crear un elemento a menos que realmente lo vaya a usar.

Es posible que tenga la tentación de probar el rendimiento algo así como $(document.createElement('div'))vs $('<div>')y obtener grandes ganancias de rendimiento al usar$(document.createElement('div')) pero ese es solo un elemento que aún no está en el DOM.

Sin embargo, al final del día, querrá usar el elemento de todos modos, por lo que la prueba real debe incluir f.ex. .appendTo ();

A ver, si pruebas lo siguiente uno contra el otro:

var e = $(document.createElement('div')).appendTo('#target');
var e = $('<div>').appendTo('#target');
var e = $('<div></div>').appendTo('#target');
var e = $('<div/>').appendTo('#target');

Notará que los resultados variarán. A veces, una forma es mejor que la otra. Y esto es solo porque la cantidad de tareas en segundo plano en su computadora cambia con el tiempo.

Ponte a prueba aquí

Por lo tanto, al final del día, desea elegir la forma más pequeña y más fácil de crear un elemento. De esa manera, al menos, sus archivos de script serán lo más pequeños posible. Probablemente sea un factor más significativo en el punto de rendimiento que la forma de crear un elemento antes de usarlo en el DOM.

Jani Hyytiäinen
fuente
Sé que esto es viejo, pero no hay necesidad de jQuery en el primer ejemplo:document.getElementById('target).appendChild(document.createElement('div'));
hisdrewness
7

Un punto es que puede ser más fácil de hacer:

$("<div class=foo id=bar style='color:white;bgcolor:blue;font-size:12pt'></div>")

Luego hacer todo eso con llamadas jquery.

Tobiah
fuente
3

Estoy usando jquery.min v2.0.3. Es mejor para mí usar lo siguiente:

var select = jQuery("#selecter");
jQuery("`<option/>`",{value: someValue, text: someText}).appendTo(select);

de la siguiente manera:

var select = jQuery("#selecter");
jQuery(document.createElement('option')).prop({value: someValue, text: someText}).appendTo(select);

El tiempo de procesamiento del primer código es mucho menor que el segundo código.

Marcel GJS
fuente