Qual è il modo più efficiente per creare elementi HTML usando jQuery?


425

Recentemente ho fatto molti pop-up modali e cosa no, per i quali ho usato jQuery. Il metodo che ho usato per creare i nuovi elementi nella pagina è stato in gran parte sulla falsariga di:

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

Tuttavia, ho la sensazione che questo non sia il metodo migliore o più efficiente per farlo. Qual è il modo migliore per creare elementi in jQuery dal punto di vista delle prestazioni?

Questa risposta ha i parametri di riferimento ai suggerimenti seguenti.


1
Prova anche a rimuovere gli stili e vedi se questo accelera le cose. Trovo l'applicazione CSS e gli aggiornamenti rallentano maggiormente le cose su grandi pagine per me.
CVertex,

3
Fai attenzione all'ottimizzazione prematura: se non lo stai facendo per centinaia di elementi DOM alla volta, o usando browser MOLTO vecchi, probabilmente non noterai alcuna differenza nelle prestazioni del browser.
Blazemonger,

1
@Blazemonger Non era così tanto che avevo bisogno di un metodo più efficiente per creare elementi DOM, ma la situazione in cui mi trovavo mi ha fatto riflettere su quali sono le alternative e su quanto potrebbero essere efficienti.
Darko Z

2
jQuery è una libreria - per questo motivo dovrai quasi sempre sostenere costi di performance generali: è come parlare con qualcuno attraverso un interprete. A meno che tu non voglia usare JavaScript non elaborato, approfitta di quanto è veloce scrivere $ ('<div>') e accettare l'hit di prestazioni.
Danny Bullis,

1
jsben.ch/#/bgvCV <= questo benchmark dovrebbe rispondere alla tua domanda
EscapeNetscape

Risposte:


307

Uso il $(document.createElement('div')); benchmarking dimostra che questa tecnica è la più veloce. Immagino che sia perché jQuery non deve identificarlo come elemento e creare l'elemento stesso.

Dovresti davvero eseguire benchmark con diversi motori Javascript e valutare il tuo pubblico con i risultati. Prendi una decisione da lì.


16
jQuery lo "aggiunge" a DOM? Dove? Questo non ha molto senso per me - dove andrebbe il div?
Strager

28
un div creato in jquery deve essere aggiunto proprio come in javascript. $ ('<div>') da solo non è attaccato al DOM fino a quando non lo aggiungi () a qualcosa.
Owen,

6
@ David - ovviamente hai ragione. Noterò che ho aggiunto il commento circa 2 anni fa proprio quando stavo iniziando a imparare jQuery. Dovresti fare un appendTo, ... Poiché i commenti erano ovviamente sbagliati, li ho rimossi.
tvanfosson,

16
Il riferimento di benchmarking è eccezionale, ma questo sta anche testando la creazione di decine di migliaia di elementi. Quando avrai MAI a che fare con così tanti elementi in una situazione tipica? È probabile che tu abbia cose più grandi di cui preoccuparti rispetto a come creare un elemento. document.createElement "Ha funzionato 39.682 volte in 0,097 secondi", mentre $ ('<div>') "Ha funzionato 12.642 in 0,068 secondi." Direi che se qualcosa può funzionare migliaia di volte in meno di un secondo, sei al sicuro.
Danny Bullis,

20
Inoltre, usando $ (document.createElement ('div')); Direi che è meno efficiente perché impiega più tempo a scrivere per l'enorme quantità di benefici che otterrai nel browser se stai creando un solo elemento alla volta qua e là. Tecnicamente, jQuery stesso è meno efficiente come libreria a causa dei costi di ricerca e delle spese generali sostenute dal suo utilizzo. Se qualcuno è così intenzionato a salvare preziosi millesimi di milli-secondo usando document.createElement invece di $ ('<div>'), allora non dovrebbero usare jQuery:], perché $ ('<div>') è uno dei motivi per cui lo usi!
Danny Bullis,

163

personalmente suggerirei (per leggibilità):

$('<div>');

alcuni numeri sui suggerimenti finora (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              

15
Dai documenti jquery: 'Quando si creano singoli elementi, utilizzare il tag di chiusura o il formato XHTML. Ad esempio, per creare uno span usa $ ("<span />") o $ ("<span> </span>") invece che senza la barra / tag di chiusura. '
tvanfosson,

6
@Owen, quel comportamento è un bug, non una funzionalità. Immondizia dentro, spazzatura fuori - succede solo che la spazzatura che ottieni è accettabile. Non fare affidamento su di esso tra le versioni di jQuery, tuttavia, a meno che non vengano modificate le specifiche per la funzione.
Strager

2
Come previsto, vedere numeri simili in Mac OS X Chrome (100ms per createElement () vs 500ms di analisi del testo) e Mac OS X Firefox (350ms contro 1000ms). Grazie per aver scritto il ciclo di prova.
Annika Backstrom,

3
@tvanfosson Questo è apparentemente cambiato, nei documenti attuali dice: "Quando il parametro ha un singolo tag (con tag di chiusura opzionale o chiusura rapida) - $ (" <img /> ") o $ (" <img> " ), $ ("<a> </a>") o $ ("<a>") - jQuery crea l'elemento utilizzando la funzione nativa createElement () di JavaScript. "
Metatron,

3
@MarcStober Nessuna offesa. È ancora qui: http://api.jquery.com/jQuery/#jQuery2 . I documenti menzionano tag di chiusura opzionali o chiusura rapida
metatron

155

Domanda:

Qual è il modo più efficiente per creare elementi HTML usando jQuery?

Risposta:

Dato che si tratta jQueryquindi penso che sia meglio usare questo approccio (pulito) (che stai usando)

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

DEMO.

In questo modo, puoi persino usare i gestori di eventi per l'elemento specifico come

$('<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');

DEMO.

Ma quando hai a che fare con molti elementi dinamici, dovresti evitare di aggiungere un evento handlersin un particolare elemento, invece, dovresti usare un gestore di eventi delegato, come

$(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');
}

DEMO.

Pertanto, se si creano e accodano centinaia di elementi con la stessa classe, ovvero ( myClass), verrà consumata meno memoria per la gestione degli eventi, poiché sarà presente un solo gestore per fare il lavoro per tutti gli elementi inseriti dinamicamente.

Aggiornamento: poiché possiamo utilizzare il seguente approccio per creare un elemento dinamico

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

Ma l' sizeattributo non può essere impostato usando questo approccio usando jQuery-1.8.0o successivamente e qui c'è una vecchia segnalazione di bug , guarda questo esempio usando jQuery-1.7.2quale mostra che l' sizeattributo è impostato 30sull'esempio sopra ma usando lo stesso approccio non possiamo impostare l' sizeattributo usando jQuery-1.8.3, qui è un violino non funzionante . Quindi, per impostare l' sizeattributo, possiamo usare il seguente approccio

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

O questo

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

Siamo in grado di passare attr/propcome un oggetto figlio ma funziona in jQuery-1.8.0 and laterversioni controllare questo esempio , ma non funzionerà in jQuery-1.7.2 or earlier(non testato in tutte le versioni precedenti).

A proposito, tratto dal jQuerybug report

Esistono diverse soluzioni. Il primo è di non usarlo affatto, poiché non ti fa risparmiare spazio e questo migliora la chiarezza del codice:

Hanno consigliato di usare il seguente approccio ( funziona anche in quelli precedenti , testato in 1.6.4)

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

Quindi, è meglio usare questo approccio, IMO. Questo aggiornamento viene effettuato dopo aver letto / trovato questa risposta e in questa risposta mostra che se si utilizza 'Size'(capital S)invece di 'size'allora funzionerà correttamente , anche inversion-2.0.2

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

Leggi anche su prop , perché c'è una differenza, Attributes vs. Propertiesvaria attraverso le versioni.


Che tipo di sintassi è questo $ ('<div />', {.........}), l'ho cercato e ne ho trovati alcuni simili usando $ ('<div>) .attr ( {......})?
Rafael Ruiz Tabares,

@RafaelRuizTabares, in $('<div>', {...})te stai passando un oggetto che contiene tutti gli attributi e in $('<div>').attr({...})te stai creando un elemento senza alcun attributo ma impostando gli attributi usando il attr()metodo in seguito.
L'Alfa,

@TheAlpha dove posso trovare informazioni su cosa posso scrivere all'interno {}? Perché vedo che sono attributi ed eventi ma per <div> usi anche html. Grazie!
Rafael Ruiz Tabares,

Cerca nel jQuery.comsito web potrebbe essere utile @RafaelRuizTabares o google esso :-)
The Alpha,

2
Questo è di gran lunga il modo più pulito e più leggibile! Probabilmente non è il modo più veloce ma sicuramente meno errori sono soggetti all'aggiunta della stringa. Grazie @TheAlpha
Ares,

37

In realtà, se lo stai facendo $('<div>'), anche jQuery utilizzerà document.createElement().

(Dai un'occhiata alla linea 117 ).

Esiste un overhead di chiamata di funzione, ma a meno che le prestazioni non siano critiche (si stanno creando centinaia [migliaia] di elementi), non ci sono molte ragioni per tornare al semplice DOM .

La semplice creazione di elementi per una nuova pagina Web è probabilmente un caso in cui ti atterrai al modo jQuery di fare le cose.


20

Se disponi di molti contenuti HTML (più di un singolo div), potresti prendere in considerazione l'idea di creare l'HTML nella pagina all'interno di un contenitore nascosto, quindi aggiornarlo e renderlo visibile quando necessario. In questo modo, gran parte del markup può essere pre-analizzato dal browser ed evitare di impantanarsi con JavaScript quando viene chiamato. Spero che sia di aiuto!


Grazie per il consiglio. Ho usato questo approccio prima, tuttavia in questo caso specifico desidero specificamente conoscere la creazione di elementi.
Darko Z,

20

Questa non è la risposta corretta alla domanda, ma vorrei comunque condividere questo ...

L'uso di document.createElement('div')JQuery e il solo salto miglioreranno notevolmente le prestazioni quando si desidera creare molti elementi al volo e aggiungere al DOM.


16

Penso che tu stia utilizzando il metodo migliore, anche se potresti ottimizzarlo per:

 $("<div/>");

11

Non hai bisogno di prestazioni grezze da un'operazione che eseguirai estremamente raramente dal punto di vista della CPU.


Dipende dalla frequenza con cui lo fai.
Rich Bradshaw,

8
L'OP sta creando un popup modale . Questa operazione non viene ripetuta migliaia di volte al secondo. Invece, viene ripetuto forse una volta ogni pochi secondi, al massimo. L'uso del jQuery(html :: String)metodo va benissimo. A meno che la situazione non sia estremamente insolita, è improbabile che si ottengano prestazioni percepite meglio . Spendi l'energia di ottimizzazione sui casi che potrebbero usarlo. Inoltre, jQuery è ottimizzato per la velocità in molti modi. Fai cose sane con esso e fidati, ma verifica che sia veloce.
yfeldblum

9

Dovrai capire che il significato delle prestazioni di creazione degli elementi è irrilevante nel contesto dell'utilizzo di jQuery in primo luogo.

Tieni presente che non esiste un vero scopo per creare un elemento a meno che non lo utilizzerai effettivamente.

Potresti essere tentato di testare le prestazioni in modo simile a $(document.createElement('div'))vs. $('<div>')e ottenere grandi guadagni in termini di prestazioni dall'utilizzo, $(document.createElement('div'))ma questo è solo un elemento che non è ancora nel DOM.

Tuttavia, alla fine della giornata, ti consigliamo di utilizzare comunque l'elemento, quindi il vero test dovrebbe includere f.ex. .appendTo ();

Vediamo, se testate quanto segue l'uno contro l'altro:

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

Noterai che i risultati varieranno. A volte un modo è più performante dell'altro. E questo solo perché la quantità di attività in background sul tuo computer cambia nel tempo.

Mettiti alla prova qui

Quindi, alla fine, vuoi scegliere il modo più piccolo e più leggibile per creare un elemento. In questo modo, almeno, i file di script saranno i più piccoli possibili. Probabilmente un fattore più significativo sul punto di prestazione rispetto al modo di creare un elemento prima di utilizzarlo nel DOM.


So che è vecchio, ma non è necessario per jQuery nel primo esempio:document.getElementById('target).appendChild(document.createElement('div'));
scomparsa


7

Un punto è che potrebbe essere più semplice fare:

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

Quindi fare tutto questo con le chiamate jquery.


3

Sto usando jquery.min v2.0.3. Per me è meglio usare quanto segue:

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

come segue:

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

Il tempo di elaborazione del primo codice è molto inferiore al secondo codice.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.