Wenn innerHTML nicht schnell genug ist

In diesem Beitrag geht es nicht um die Vor- und Nachteile von innerHTML vs. W3C-DOM-Methoden. Das wurde an anderer Stelle gehasht und wiedergewärmt. Stattdessen zeige ich, wie Sie die Verwendung von innerHTML kombinieren können und DOM-Methoden, um Ihren Code potenziell hundertmal schneller als innerHTML zu machen allein, wenn mit einer großen Anzahl von Elementen gearbeitet wird.

In einigen Browsern (insbesondere Firefox), obwohl innerHTML ist im Allgemeinen viel schneller als DOM-Methoden, es verbringt unverhältnismäßig viel Zeit damit, vorhandene Elemente zu löschen, anstatt neue zu erstellen. Wenn wir dies wissen, können wir die Geschwindigkeit des Zerstörens von Elementen durch Entfernen ihrer Eltern mithilfe der Standard-DOM-Methoden mit dem Erstellen neuer Elemente mithilfe von innerHTML kombinieren . (Diese Technik habe ich während der Entwicklung von RegexPal entdeckt und ist eine der beiden wichtigsten Leistungsoptimierungen. Die andere ist die One-Shot-Markup-Generierung zur Hervorhebung von Übereinstimmungen, wodurch vermieden wird, dass Übereinstimmungen wiederholt oder einzeln referenziert werden müssen.) P>

Der Code:

function replaceHtml(el, html) {
	var oldEl = typeof el === "string" ? document.getElementById(el) : el;
	/*@cc_on // Pure innerHTML is slightly faster in IE
		oldEl.innerHTML = html;
		return oldEl;
	@*/
	var newEl = oldEl.cloneNode(false);
	newEl.innerHTML = html;
	oldEl.parentNode.replaceChild(newEl, oldEl);
	/* Since we just removed the old element from the DOM, return a reference
	to the new element, which can be used to restore variable references. */
	return newEl;
};

Sie können das obige als el = replaceHtml(el, newHtml) verwenden statt el.innerHTML = newHtml .

innerHTML ist schon ziemlich schnell ... ist das wirklich gerechtfertigt?

Das hängt davon ab, wie viele Elemente Sie überschreiben. In RegexPal löst jedes Keydown-Ereignis potenziell die Zerstörung und Erstellung von Tausenden von Elementen aus (damit die Syntax- und Match-Hervorhebung funktioniert). In solchen Fällen hat der obige Ansatz enorme positive Auswirkungen. Sogar etwas so Einfaches wie el.innerHTML += str oder el.innerHTML = "" könnte eine Leistungskatastrophe sein, wenn das Element, das Sie aktualisieren, einige tausend untergeordnete Elemente hat.

Ich habe eine Seite erstellt, mit der Sie den Leistungsunterschied von innerHTML einfach testen können und mein replaceHtml Funktion mit unterschiedlicher Anzahl von Elementen. Probieren Sie es zum Vergleich in einigen Browsern aus. Im Folgenden finden Sie einige Beispiele für typische Ergebnisse von Firefox 2.0.0.6 auf meinem System:

1000 elements...
innerHTML (destroy only): 156ms
innerHTML (create only): 15ms
innerHTML (destroy & create): 172ms
replaceHtml (destroy only): 0ms (faster)
replaceHtml (create only): 15ms (~ same speed)
replaceHtml (destroy & create): 15ms (11.5x faster)

15000 elements...
innerHTML (destroy only): 14703ms
innerHTML (create only): 250ms
innerHTML (destroy & create): 14922ms
replaceHtml (destroy only): 31ms (474.3x faster)
replaceHtml (create only): 250ms (~ same speed)
replaceHtml (destroy & create): 297ms (50.2x faster)

Ich denke die Zahlen sprechen für sich. Vergleichbare Leistungsverbesserungen sind auch in Safari zu sehen. In Opera replaceHtml ist normalerweise immer noch schneller als innerHTML , aber mit einem schmaleren Rand. Im IE einfache Verwendung von innerHTML ist normalerweise schneller als das Mischen mit DOM-Methoden, aber nicht annähernd mit den gleichen Margen, wie Sie oben sehen können. Trotzdem wird die bedingte Kompilierungsfunktion von IE verwendet, um die relativ geringfügige Leistungseinbuße zu vermeiden, indem einfach innerHTML verwendet wird mit diesem Browser.


No