Warum ist element.innerHTML+=schlechter Code?

Jedes Mal innerHTML gesetzt ist, muss das HTML geparst, ein DOM erstellt und in das Dokument eingefügt werden. Das braucht Zeit.

Wenn beispielsweise elm.innerHTML hat Tausende von divs, Tabellen, Listen, Bildern usw. und ruft dann .innerHTML += ... auf wird den Parser veranlassen, das ganze Zeug erneut zu analysieren erneut. Dies könnte auch Verweise auf bereits erstellte DOM-Elemente unterbrechen und weiteres Chaos verursachen. In Wirklichkeit möchten Sie nur ein einzelnes neues Element an das Ende anhängen.

Rufen Sie besser einfach appendChild an :

var newElement = document.createElement('div');
newElement.innerHTML = '<div>Hello World!</div>';
elm.appendChild(newElement);​​​​​​​​​​​​​​​​

Auf diese Weise wird der vorhandene Inhalt von elm werden nicht erneut geparst.

HINWEIS: Es ist möglich, dass [einige] Browser intelligent genug sind, um den += zu optimieren -Operator und den vorhandenen Inhalt nicht erneut analysieren. Ich habe das nicht recherchiert.


Ja, elm.innerHTML += str; ist eine sehr schlechte idee.
Verwenden Sie elm.insertAdjacentHTML( 'beforeend', str ) als perfekte Alternative.

Die typische Antwort "Browser muss DOM neu erstellen" wird der Frage wirklich nicht gerecht:

  1. Zuerst muss der Browser alle Elemente unter elm, jede ihrer Eigenschaften und alle ihre Texte, Kommentare und Prozessknoten durchgehen und sie maskieren, um einen String zu erstellen.

  2. Dann haben Sie eine lange Zeichenfolge, an die Sie anhängen. Dieser Schritt ist in Ordnung.

  3. Drittens, wenn Sie innerHTML setzen, muss der Browser alle Elemente, Eigenschaften und Knoten entfernen, die er gerade durchlaufen hat.

  4. Dann parst es den String, baut aus allen Elementen, Eigenschaften und Knoten auf, die es gerade zerstört hat, um ein neues DOM-Fragment zu erstellen, das größtenteils identisch ist.

  5. Schließlich fügt es die neuen Knoten hinzu, und der Browser muss das Ganze layouten. Dies kann vermeidbar sein (siehe die Alternative unten), aber selbst wenn der/die angehängte(n) Knoten ein Layout erfordert, würden alte Knoten ihre Layout-Eigenschaften zwischenspeichern, anstatt neu berechnet zu werden.

  6. Aber es ist noch nicht fertig! Der Browser muss auch alte Knoten recyceln, indem er alle scannt Javascript-Variablen.

Probleme:

  • Einige Eigenschaften werden möglicherweise nicht von HTML wiedergegeben, beispielsweise der aktuelle Wert von <input> gehen verloren und werden auf den Anfangswert im HTML zurückgesetzt.

  • Wenn Sie Event-Handler auf den alten Knoten haben, werden sie zerstört und Sie müssen sie alle neu anhängen.

  • Wenn Ihr js-Code auf alte Knoten verweist, werden diese nicht zerstört, sondern verwaisen. Sie gehören zum Dokument, befinden sich aber nicht mehr im DOM-Baum. Wenn Ihr Code darauf zugreift, passiert möglicherweise nichts oder es wird ein Fehler ausgegeben.

  • Beide Probleme bedeuten, dass es mit js-Plugins unfreundlich ist - die Plugins können Handler anhängen oder auf alte Knoten verweisen und Speicherverluste verursachen.

  • Wenn Sie sich angewöhnen, DOM-Manipulationen mit innerHTML durchzuführen, können Sie versehentlich Eigenschaften ändern oder andere Dinge tun, die Sie nicht wollten.

  • Je mehr Knoten Sie haben, desto ineffizienter ist dies, desto mehr Batteriesaft für nichts.

Kurz gesagt, es ist ineffizient, es ist fehleranfällig, es ist einfach faul und uninformiert.

Die beste Alternative ist Element.insertAdjacentHTML , die ich nicht in anderen Antworten gesehen habe:

elm.insertAdjacentHTML( 'beforeend', str )

Fast derselbe Code, ohne die Probleme von innerHTML. Kein Neuaufbau, kein verlorener Handler, kein Zurücksetzen der Eingabe, weniger Speicherfragmentierung, keine schlechte Angewohnheit, keine manuelle Elementerstellung und -zuweisung.

Es ermöglicht Ihnen, HTML-Strings in Elemente in einer Zeile einzufügen, einschließlich Eigenschaften, und erlaubt Ihnen sogar, zusammengesetzte und mehrere Elemente einzufügen. Seine Geschwindigkeit ist optimiert - in Mozillas Test beträgt sie 150 mal schneller.

Falls Ihnen jemand sagt, dass es nicht browserübergreifend ist, ist es so nützlich, dass es HTML5-Standard ist und in allen Browsern verfügbar ist.

Schreiben Sie niemals elm.innerHTML+= nochmal.


Die Alternative ist .createElement() , .textContent , und .appendChild() . Anhängen mit += ist nur ein Problem, wenn Sie mit vielen Daten zu tun haben.

Demo: http://jsfiddle.net/ThinkingStiff/v6WgG/

Skript

var elm = document.getElementById( 'targetID' ),
    div = document.createElement( 'div' );
div.textContent = 'goodbye world';
elm.appendChild( div );

HTML

<div id="targetID">hello world</div>