Was ist der effizienteste Weg, um HTML-Elemente mit jQuery zu erstellen?

425

In letzter Zeit habe ich viele modale Fenster-Popups erstellt und was nicht, für die ich jQuery verwendet habe. Die Methode, mit der ich die neuen Elemente auf der Seite erstellt habe, war überwiegend wie folgt:

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

Ich habe jedoch das Gefühl, dass dies nicht die beste oder effizienteste Methode ist. Was ist der beste Weg, um Elemente in jQuery aus Sicht der Leistung zu erstellen?

Diese Antwort enthält die Benchmarks für die folgenden Vorschläge.

Darko Z.
quelle
1
Experimentieren Sie auch mit dem Entfernen von Stilen und prüfen Sie, ob dies die Dinge beschleunigt. Ich finde, dass CSS-Anwendungen und Updates die Dinge auf großen Seiten für mich am meisten verlangsamen.
CVertex
3
Vorsicht vor vorzeitiger Optimierung - Wenn Sie dies nicht für Hunderte von DOM-Elementen gleichzeitig tun oder SEHR alte Browser verwenden, werden Sie wahrscheinlich keinen Unterschied in der Leistung des Browsers bemerken.
Blazemonger
1
@Blazemonger Es war nicht so sehr, dass ich eine effizientere Methode zum Erstellen von DOM-Elementen brauchte , aber die Situation, in der ich mich befand, ließ mich darüber nachdenken, welche Alternativen es gibt und wie effizient sie sein könnten.
Darko Z
2
jQuery ist eine Bibliothek - aus diesem Grund fallen fast immer Overhead-Leistungskosten an: Es ist, als würde man über einen Interpreter mit jemandem sprechen. Wenn Sie kein unformatiertes JavaScript verwenden möchten, nutzen Sie die Geschwindigkeit, mit der $ ('<div>') geschrieben und der Leistungseinbruch akzeptiert wird.
Danny Bullis
1
jsben.ch/#/bgvCV <= dieser Benchmark sollte Ihre Frage beantworten
EscapeNetscape

Antworten:

307

Ich benutze $(document.createElement('div')); Benchmarking zeigt, dass diese Technik die schnellste ist. Ich spekuliere, weil jQuery es nicht als Element identifizieren und das Element selbst erstellen muss.

Sie sollten wirklich Benchmarks mit verschiedenen Javascript-Engines ausführen und Ihre Zielgruppe mit den Ergebnissen abwägen. Treffen Sie von dort aus eine Entscheidung.

Strager
quelle
16
jQuery "hängt" es an DOM? Wo? Das macht für mich nicht viel Sinn - wohin würde der Div gehen?
Strager
28
Ein in jquery erstelltes div muss wie in javascript hinzugefügt werden. $ ('<div>') selbst wird erst an das DOM angehängt, wenn Sie es an etwas anhängen ().
Owen
6
@ David - offensichtlich hast du recht. Ich werde bemerken, dass ich den Kommentar vor ungefähr 2 Jahren hinzugefügt habe, als ich anfing, jQuery zu lernen. Sie müssten eine appendTo, ... Da die Kommentare offensichtlich falsch waren, habe ich sie entfernt.
Tvanfosson
16
Die Benchmarking-Referenz ist großartig, aber dies testet auch die Erstellung von Zehntausenden von Elementen. Wann werden Sie sich in einer typischen Situation jemals mit so vielen Elementen befassen? Wahrscheinlich müssen Sie sich größere Sorgen machen, als ein Element zu erstellen. document.createElement "lief 39.682 Mal in 0,097 Sekunden", während $ ('<div>') "12.642 Mal in 0,068 Sekunden lief". Ich würde sagen, wenn etwas in weniger als einer Sekunde tausende Male laufen kann, sind Sie in Sicherheit.
Danny Bullis
20
Verwenden Sie außerdem $ (document.createElement ('div')); Ich würde sagen, es ist weniger effizient, da das Schreiben für den im Wesentlichen geringen Nutzen, den Sie im Browser erhalten, länger dauert, wenn Sie hier und da jeweils nur ein Element erstellen. Technisch gesehen ist jQuery selbst als Bibliothek aufgrund der Nachschlagekosten und des damit verbundenen Overheads weniger effizient. Wenn jemand so sehr darauf bedacht ist, mit document.createElement anstelle von $ ('<div>') wertvolle Tausendstel Millisekunden einzusparen, sollte er jQuery nicht verwenden:], weil $ ('<div>') ist einer der Gründe, warum Sie es verwenden!
Danny Bullis
163

persönlich würde ich vorschlagen (zur besseren Lesbarkeit):

$('<div>');

Einige Zahlen zu den bisherigen Vorschlägen (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
quelle
15
Aus den jquery-Dokumenten: 'Verwenden Sie beim Erstellen einzelner Elemente das schließende Tag oder das XHTML-Format. Verwenden Sie zum Erstellen eines Bereichs beispielsweise $ ("<span />") oder $ ("<span> </ span>") anstelle des schließenden Schrägstrichs / Tags. '
Tvanfosson
6
@Owen, dieses Verhalten ist ein Fehler, keine Funktion. Müll rein, Müll raus - es kommt einfach so vor, dass der Müll, den Sie bekommen, akzeptabel ist. Verlassen Sie sich jedoch nicht zwischen jQuery-Versionen darauf, es sei denn, die Spezifikation für die Funktion ändert sich.
Strager
2
Wie erwartet werden ähnliche Zahlen in Mac OS X Chrome (100 ms für createElement () vs. 500 ms Textanalyse) und Mac OS X Firefox (350 ms vs. 1000 ms) angezeigt. Vielen Dank, dass Sie die Testschleife geschrieben haben.
Annika Backstrom
3
@tvanfosson Dies hat sich anscheinend geändert. In den aktuellen Dokumenten heißt es: "Wenn der Parameter ein einzelnes Tag hat (mit optionalem schließendem Tag oder schnellem Schließen) - $ (" <img /> ") oder $ (" <img> ") ), $ ("<a> </a>") oder $ ("<a>") - jQuery erstellt das Element mit der nativen JavaScript-Funktion createElement (). "
Metatron
3
@MarcStober Keine Beleidigung genommen. Es ist immer noch hier: http://api.jquery.com/jQuery/#jQuery2 . Die Dokumente erwähnen optionales schließendes Tag oder schnelles Schließen
Metatron
155

Frage:

Was ist der effizienteste Weg, um HTML-Elemente mit jQuery zu erstellen?

Antworten:

Da es ungefähr jQuerydann ist, denke ich, ist es besser, diesen (sauberen) Ansatz zu verwenden (den Sie verwenden)

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

DEMO.

Auf diese Weise können Sie sogar Ereignishandler für das jeweilige Element wie verwenden

$('<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.

Wenn Sie jedoch mit vielen dynamischen Elementen arbeiten, sollten Sie das Hinzufügen eines Ereignisses handlersin einem bestimmten Element vermeiden. Stattdessen sollten Sie einen delegierten Ereignishandler wie verwenden

$(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.

Wenn Sie also Hunderte von Elementen mit derselben Klasse erstellen und anhängen, dh ( myClass), wird weniger Speicher für die Ereignisbehandlung benötigt, da nur ein Handler für alle dynamisch eingefügten Elemente zur Verfügung steht.

Update: Da wir den folgenden Ansatz verwenden können, um ein dynamisches Element zu erstellen

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

Das sizeAttribut kann jedoch nicht mit diesem Ansatz jQuery-1.8.0oder später festgelegt werden. Hier ist ein alter Fehlerbericht . Sehen Sie sich dieses Beispiel an , jQuery-1.7.2das zeigt, dass das sizeAttribut auf 30das obige Beispiel eingestellt ist, aber denselben Ansatz verwendet, mit dem wir das sizeAttribut jQuery-1.8.3hier nicht festlegen können ist eine nicht funktionierende Geige . Um das sizeAttribut festzulegen, können wir den folgenden Ansatz verwenden

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

Oder dieses

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

Wir können attr/propals untergeordnetes Objekt übergeben, aber es funktioniert in jQuery-1.8.0 and laterVersionen. Überprüfen Sie dieses Beispiel, aber es funktioniert nicht in jQuery-1.7.2 or earlier(nicht in allen früheren Versionen getestet).

Übrigens, aus dem jQueryFehlerbericht entnommen

Es gibt verschiedene Lösungen. Das erste ist, es überhaupt nicht zu verwenden, da es Ihnen keinen Platz spart und dies die Klarheit des Codes verbessert:

Sie rieten zu folgendem Ansatz ( funktioniert auch in früheren , getestet in 1.6.4)

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

Es ist also besser, diesen Ansatz zu verwenden, IMO. Dieses Update wird , nachdem ich gelesen / gefunden diese Antwort und in dieser Antwort zeigt , dass , wenn Sie verwenden , 'Size'(capital S)anstatt 'size'es dann wird nur gut funktionieren , auch inversion-2.0.2

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

Lesen Sie auch über Requisiten , da es einen Unterschied gibt Attributes vs. Properties, der von Version zu Version unterschiedlich ist.

Das Alpha
quelle
Was für eine Sintax ist das $ ('<div />', {.........}), ich habe danach gesucht und mit $ ('<div>) .attr ( {......})?
Rafael Ruiz Tabares
@RafaelRuizTabares, in dem $('<div>', {...})Sie ein Objekt übergeben, das alle Attribute enthält, und in dem $('<div>').attr({...})Sie ein Element ohne Attribute erstellen, die Attribute jedoch attr()später mithilfe der Methode festlegen.
Die Alpha
@TheAlpha Wo finde ich Informationen darüber, was ich in {} schreiben kann? Weil ich sehe, dass es sich um Attribute und Ereignisse handelt, aber für <div> verwenden Sie auch HTML. Vielen Dank!
Rafael Ruiz Tabares
Suche jQuery.comWebsite könnte hilfreich sein @RafaelRuizTabares, oder googeln Sie es :-)
The Alpha
2
Dies ist bei weitem der sauberste und lesbarere Weg! Wahrscheinlich nicht der schnelle Weg, aber sicherlich weniger fehleranfällig für das Hinzufügen von Zeichenfolgen. Vielen Dank @TheAlpha
Ares
37

Wenn Sie dies tun $('<div>'), wird jQuery auch verwendet document.createElement().

(Schauen Sie sich einfach Zeile 117 an. )

Es gibt einen gewissen Aufwand für Funktionsaufrufe, aber wenn die Leistung nicht kritisch ist (Sie erstellen Hunderte [Tausende] von Elementen), gibt es nicht viel Grund, auf einfaches DOM zurückzugreifen .

Das Erstellen von Elementen für eine neue Webseite ist wahrscheinlich ein Fall, in dem Sie sich am besten an die jQuery- Methode halten.

Edwin
quelle
20

Wenn Sie viel HTML-Inhalt haben (mehr als nur ein einziges Div), können Sie den HTML-Code in die Seite in einem versteckten Container einbauen, ihn dann aktualisieren und bei Bedarf sichtbar machen. Auf diese Weise kann ein großer Teil Ihres Markups vom Browser vorab analysiert werden, um zu vermeiden, dass JavaScript beim Aufrufen ins Stocken gerät. Hoffe das hilft!

Collin Allen
quelle
Danke für den Hinweis. Ich habe diesen Ansatz bereits verwendet, möchte jedoch in diesem speziellen Fall speziell wissen, wie Elemente erstellt werden.
Darko Z
20

Dies ist nicht die richtige Antwort auf die Frage, aber ich möchte dies trotzdem teilen ...

Wenn Sie nur document.createElement('div')JQuery verwenden und überspringen, wird die Leistung erheblich verbessert, wenn Sie viele Elemente im laufenden Betrieb erstellen und an DOM anhängen möchten.

Irshad
quelle
16

Ich denke, Sie verwenden die beste Methode, obwohl Sie sie optimieren könnten, um:

 $("<div/>");
Tvanfosson
quelle
11

Sie benötigen keine Rohleistung für einen Vorgang, den Sie aus Sicht der CPU äußerst selten ausführen.

Yfeldblum
quelle
Kommt darauf an, wie oft du es machst.
Rich Bradshaw
8
Das OP erstellt ein modales Popup . Dieser Vorgang wird nicht tausendmal pro Sekunde wiederholt. Stattdessen wird es maximal alle paar Sekunden wiederholt. Die Verwendung der jQuery(html :: String)Methode ist vollkommen in Ordnung. Wenn die Situation nicht äußerst ungewöhnlich ist, ist es unwahrscheinlich, dass eine besser wahrgenommene Leistung erzielt wird . Geben Sie die Optimierungsenergie für die Fälle aus, in denen sie verwendet werden könnten. Darüber hinaus ist jQuery in vielerlei Hinsicht auf Geschwindigkeit optimiert. Machen Sie vernünftige Dinge damit und vertrauen Sie darauf, dass es schnell ist.
Yfeldblum
9

Sie müssen verstehen, dass die Bedeutung der Leistung bei der Elementerstellung für die Verwendung von jQuery in erster Linie irrelevant ist.

Denken Sie daran, dass es keinen wirklichen Zweck gibt, ein Element zu erstellen, es sei denn, Sie werden es tatsächlich verwenden.

Sie könnten versucht sein, Leistungstests wie $(document.createElement('div'))vs. zu testen $('<div>')und durch die Verwendung große Leistungssteigerungen zu erzielen, $(document.createElement('div'))aber das ist nur ein Element, das noch nicht im DOM enthalten ist.

Am Ende des Tages sollten Sie das Element jedoch trotzdem verwenden, sodass der eigentliche Test f.ex enthalten sollte. .Anhängen();

Mal sehen, ob Sie Folgendes gegeneinander testen:

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

Sie werden feststellen, dass die Ergebnisse variieren. Manchmal ist ein Weg besser als der andere. Dies liegt nur daran, dass sich die Anzahl der Hintergrundaufgaben auf Ihrem Computer im Laufe der Zeit ändert.

Testen Sie sich hier

Letztendlich möchten Sie also die kleinste und am besten lesbare Methode zum Erstellen eines Elements auswählen. Auf diese Weise werden zumindest Ihre Skriptdateien so klein wie möglich. Wahrscheinlich ein wichtigerer Faktor für den Leistungspunkt als die Art und Weise, wie ein Element erstellt wird, bevor Sie es im DOM verwenden.

Jani Hyytiäinen
quelle
Ich weiß, dass dies alt ist, aber im ersten Beispiel ist jQuery nicht erforderlich:document.getElementById('target).appendChild(document.createElement('div'));
hisdrewness
7

Ein Punkt ist, dass es einfacher sein kann:

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

Dann, um all das mit jquery-Aufrufen zu tun.

Tobiah
quelle
3

Ich benutze jquery.min v2.0.3. Es ist für mich besser, Folgendes zu verwenden:

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

wie folgt:

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

Die Verarbeitungszeit des ersten Codes ist viel kürzer als die des zweiten Codes.

Marcel GJS
quelle