2008-09-22 15 views
21

Ich habe dieses schlechte Gefühl darüber, wie ich größere Mengen von HTML einfügen. Nehmen wir an, wir haben:jquery: schnellste DOM-Einfügung?

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

und ich möchte dies in

$("#mydiv")

vorher setzen Ich habe so etwas wie

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

Ist es richtig, th bei jQuery ist html zu analysieren, um DOM-Objekte zu erstellen? Gut, das ist, was ich irgendwo lesen (UPDATE: Ich meinte, dass die ich gelesen habe, analysiert jQuery die html die gesamte DOM-Baum von Hand zu erstellen - seine Unsinn richtig ?! ), also habe ich meinen Code:

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

Fühlt sich schneller an, oder? Und ist es richtig, dass dies äquivalent ist zu:

document.getElementById("mydiv").innerHTML += html? Oder macht Jquery noch ein paar zusätzliche teure Sachen im Hintergrund?

Würde gerne Alternativen lernen.

Antwort

21

innerHTML ist bemerkenswert schnell, und in vielen Fällen werden Sie die besten Ergebnisse nur die Einstellung (ich würde nur append verwenden) erhalten.

Wenn jedoch bereits viel in "mydiv" vorhanden ist, erzwingen Sie, dass der Browser den gesamten Inhalt erneut parst und rendert (alles, was vorher dort war, plus all Ihre neuen Inhalte). Sie können dies vermeiden, indem ein Dokumentfragment auf „mydiv“ anhängt statt:

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

Auf diese Weise nur Ihre neue Inhalte (unvermeidlich) analysiert wird und die vorhandenen Inhalte nicht.

EDIT: Meine schlechte ... Ich habe festgestellt, dass innerHTML nicht gut auf Dokumentfragmente unterstützt wird. Sie können die gleiche Technik für jeden Knotentyp verwenden. Für Ihr Beispiel könnten Sie den Root-Tabellenknoten und legen Sie die Innerhtml in dem schaffen:

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

Das funktionierte für mich, aber ich musste append() verwenden, nicht appendChild(). Tippfehler oder hat der Methodenname geändert? –

+0

Ich bin mir nicht sicher, wie das vorbeigekommen sein könnte, aber ich glaube nicht, dass es eine umbenannte Methode ist. Ich werde meinen Beitrag aktualisieren. – Prestaul

+1

appendChild() ist die w3c-DOM-Methode, die das gleiche wie append() in jQuery (ungefähr) tut – xj9

1

Für Anfänger, schreiben Sie ein Skript, das mal wie lange es dauert, 100 oder 1000 Mal mit jeder Methode zu tun.

Um sicherzustellen, dass die Wiederholungen nicht irgendwie optimiert sind - ich bin kein Experte für JavaScript-Engines - variieren Sie den HTML-Code, den Sie jedes Mal einfügen, indem Sie "0001" und dann "0002" und dann "0003" eingeben 'in einer bestimmten Zelle des Tisches.

9

Was möchten Sie vermeiden? "Ein schlechtes Gefühl" ist unglaublich vage. Wenn Sie gehört haben "das DOM ist langsam" und entschieden "das DOM zu vermeiden", dann ist das unmöglich. Jede Methode zum Einfügen von Code in eine Seite, einschließlich innerHTML, führt dazu, dass DOM-Objekte erstellt werden. Das DOM ist die Darstellung des Dokuments im Speicher Ihres Browsers. Sie wollen DOM-Objekte erstellt werden.

Der Grund, warum Leute sagen "das DOM ist langsam" ist, weil das Erstellen von Elementen mit document.createElement(), die die offizielle DOM-Schnittstelle zum Erstellen von Elementen ist, langsamer ist als die Verwendung der Nicht-Standard-Eigenschaft innerHTML in einigen Browsern. Dies bedeutet nicht, dass das Erstellen von DOM-Objekten schlecht ist, es ist erforderlich DOM-Objekte zu erstellen, sonst würde Ihr Code überhaupt nichts tun.

-1

Sie erwähnen, dass Sie an Alternativen interessiert sind. Wenn Sie sich die Auflistung von DOM-related jQuery plugins ansehen, werden Sie einige finden, die sich dem programmatischen Erzeugen von DOM-Bäumen widmen. Siehe zum Beispiel SuperFlyDom oder DOM Elements Creator; aber es gibt andere.

+0

diese würden DOM-Fragmente verwenden, würden sie nicht? –

2

Die Antwort über ein DOM-Fragment unter Verwendung von auf dem richtigen Weg ist. Wenn Sie ein Bündel von HTML-Objekten haben, die Sie ständig in das DOM einfügen, werden Sie einige Geschwindigkeitsverbesserungen mit dem Fragment sehen. Dieser Beitrag von John Resig erklärt es ziemlich gut: http://ejohn.org/blog/dom-documentfragments/

+0

Er hat nicht erwähnt, dass er ein Fragment zu mehr als einem Elemente setzen möchte. Seine Frage zeigt an, dass er einen html frag in ein Element setzen möchte. Außerdem wird "Dokumentfragment" implizit in jQuery erstellt. – galambalazs

32

Versuchen Sie Folgendes:

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

Die anderen Antworten, einschließlich der akzeptierte Antwort, sind langsamer von 2-10x: jsperf.

Die akzeptierte Antwort funktioniert nicht in 6 IE, 7 und 8, weil Sie nicht innerHTML eines <table> Element festlegen können, aufgrund eines Fehlers in IE: jsbin.

+1

+1, das HTML als String zu erstellen und ein einzelnes 'append' anstelle jedes Elements mit jquery zu verwenden, erhöhte die Leistung in meinem Fall um eine Größenordnung (erstellte 280 divs mit jeweils einer Tabelle und ein paar Zeilen , dauerte 12 Sekunden, jetzt ist es auf 1.1).Obwohl Sie vielleicht die Beleidigungen reduzieren möchten ...;) – falstro

+1

+1 für das Posten eines jsperf.com Links, wenn das genau das ist, was benötigt wird –

+0

Ihr Test ist unehrlich. Es erstellt ein neues Dom-Fragment für jedes Element. Sie sollen alle Elemente an ein Dom-Fragment anhängen und dann in den Dom-Baum einfügen. Hier ist ein echter Test http://jsperf.com/scriptjunkie-premature-7 –

1

Der schnellste Weg Artikel

Der schnellste Weg zum DOM-Baum anhängen anhängen ist, alle Ihre append in zu einem einzigen DOM-Fragment puffern, dann das dom Fragment auf das dom anhängen.

Dies ist die Methode, die ich in meiner Game-Engine verwende.

//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); 

Mit diesem Objekt ich in der Lage bin zu dem Bildschirm ~ 40-mal pro Sekunde in Firefox 4.

Hier ist ein Use Case ~ 1000 Elemente zu machen.

+0

Ich schrieb diesen Code danke! Die Frage ist: "Was ist der schnellste Weg, um an das Dom anzuhängen?" Der Typ fügt einen Tisch ein. Es spielt keine Rolle, ob es eine Tabelle oder ein Div ist. Offensichtlich hast du meine Antwort nicht sehr gut gelesen. Und zu sagen, dass perzeptuelles Einfügen schneller ist als Puffern und Anhängen, ist immer noch völlig falsch. Wenn du die Relevanz, die dir zu schlecht ist, nicht verstehen kannst. –

+0

Es überrascht mich nicht, wenn Sie es "geschrieben" haben, es gibt nichts Magisches daran, ich habe nicht einmal gesagt, dass es an sich falsch ist, die Sache ist, dass es immer noch nicht mit der Frage verbunden ist. Und immer noch gibt Ihnen nicht das Recht, die Antwort eines anderen zu nennen, wer die Frage liest, um unehrlich zu sein. Du bist dem gesunden Menschenverstand gegenüber unehrlich. – galambalazs

+0

Was bedeutet das gemein zum gesunden Menschenverstand? Der Typ wollte eine Anzahl von tabellenbezogenen Knoten einfügen. Ein DOM-Fragment wird dies tun. Du scheinst nur so zu sein, als hättest du einen Überlegenheitskomplex. –

0

Ich erstelle eine riesige Zeichenfolge mit und dann diese Zeichenfolge mit jquery anhängen. Funktioniert gut und schnell, für mich.