Document Object Model - DOM

DOM (Document Object Model) ist zwar allgegenwärtig in der Webentwicklung, es ist aber trotzdem schwierig, es genau zu definieren. Dazu kommt auch noch das virtuelle DOM, das Schatten-DOM, DOM-Level 1, 2, 3 usw… Dieser Blogeintrag ist mein Versuch, die Begrifflichkeiten rund um das DOM zu beleuchten und ein wenig zu strukturieren.

Warum DOM?

Bevor wir zur Definition übergehen, versuchen wir zu verstehen, warum die Leute das Konzept überhaupt einführen würden. Stellt euch vor, man schreibt 1997 und ihr seid Webentwickler. Ihr möchtet Webseiten mit client-seitiger Interaktivität erstellen. Die browserübergreifende Kompatibilität war nie einfach, aber Internet Explorer 4 und Netscape Navigator 4 verfolgten plötzlich unterschiedliche Ansätze bei der Steuerung von HTML-Elementen. Um eine solche Entwicklung des Internets zu verhindern, begann das World Wide Web Consortium (W3C) mit der Arbeit am DOM.

Daher hilft uns DOM, in allen Browsern (mehr oder weniger) auf die gleiche Weise mit unseren Webseiten zu interagieren.

Definition

DOM ist also ein vereinbarter Standard, der festlegt, auf welche Art und Weise man Elemente einer Webseite ansprechen und steuern soll (z. B. welche Methode aufgerufen werden soll und welche Parameter verwendet werden sollen). Kommt euch das bekannt vor? Ja! Dies ist die Definition einer Schnittstelle! In der Tat ist DOM eine plattform- und sprachneutrale Abstraktionsschicht, über die Programme und Skripte dynamisch auf Inhalt, Struktur und Stil von Dokumenten zugreifen und diese aktualisieren können. Ohne sie hätte JavaScript kein Modell oder keine Vorstellung von Webseiten, HTML-Dokumenten und ihren Komponenten. Die DOM-Schnittstelle besteht aus mehreren APIs (oder Modulen). Das Kern-DOM enthält grundlegende Definitionen von Dokument-Objekten und deren Bestandteilen (Attributen, Elementen usw.). Weitere Module umfassen Event-Unterstützung, Stylesheet-Verwaltung, XPath-Nutzung usw. Ihr müsst nichts Besonderes tun, um das DOM zu verwenden. Wenn eine Webseite geladen wird, erstellt die Layout-Engine des Browsers (z. B. Blink, WebKit und Gecko) das DOM der Seite im Speicher. Wie sieht es aus? Das Modell repräsentiert ein Dokument als eine logische Baumstruktur. Jeder Zweig des Baums endet in einem Knoten (einem HTML-Tag), und jeder Knoten enthält Objekte. An Knoten können auch Event-Handler angehängt werden. Sobald ein Ereignis ausgelöst wird, werden die entsprechenden Event-Handler ausgeführt. Somit ist das DOM die objektbasierte Darstellung des HTML-Dokuments und der API zur Bearbeitung dieser Objekte.

Sobald ihr das Gefühl habt, das DOM verstanden zu haben, werden die Dinge komplizierter. Schon mal was von DOM Level 4 gehört? Schatten-DOM? Virtuelles DOM? Inkrementelles DOM? Lasst uns diese Begriffe auch analysieren.

Dom Level: 0, 1, 2, 3, 4…

Bereits 1995 führte Nescape 2 Level 0 DOM ein (also die erste DOM-Implementierung). Mit Level 1 wurde es zur W3C-Empfehlung für alle Browser. Grundsätzlich repräsentiert ein DOM-Level einfach so etwas wie eine Release-Version in der Weiterentwicklung von DOM: Die nächsten Level (Spezifikationen) bauen auf den vorherigen auf und fügen einige neue Module, Methoden und Features hinzu. Mit Level 4 DOM ist allerdings Schluss damit. Der Standard wird nicht mehr als eine Reihe von Levels beschrieben, sondern als Momentaufnahme der lebenden Spezifikation. Kontinuierliche Lieferung (Continuous Delivery) sozusagen. Früher war es wichtig zu wissen, zu welchem Level die Funktion gehört, da z.B. DOM Level 2 besser unterstützt wurde als DOM Level 3. Heutzutage ist es nicht mehr relevant, obwohl man diese Versionsnummer möglicherweise immer noch im Web findet.

Lasst uns aber lieber über aktuellere Konzepte reden - über das Schatten-DOM.

Schatten-DOM

Beginnen wir noch einmal mit der Frage, warum wir dieses Konzept überhaupt brauchen. Stellen euch diesmal vor, ihr habt einige Webkomponenten oder nur Teile von HTML / CSS, die ihr woanders wiederverwenden möchtet. Wie könnt ihr sicherstellen, dass das Styling nicht überschrieben oder verzerrt wird? Was wir also brauchen, ist eine iframe-ähnliche Kapselung. Die Shadow DOM-API bietet genau dies - sie ermöglich Styling von einen bestimmten Bereich, geschützt vor Einflüssen von außen. Ohne Tools oder Namenskonventionen könnt ihr Implementierungsdetails ausblenden, das gewünschte Styling und Struktur sicherstellen und in sich geschlossene Komponenten in Vanilla JavaScript erstellen. Denkt an . Es besteht offensichtlich aus mehr als nur einem Element, doch die „Innenelemente“ sind von Webentwicklern verborgen. Stattdessen werden nur einige CSS-Eigenschaften zur Anpassung verfügbar gemacht. Der Browser kann jedoch auf die „Innenelemente“ zugreifen und mit denselben guten alten Divs und Spans erstellen. Oh, wenn wir über Browser sprechen … überprüft die Unterstützung von Shadow-DOM bei caniuse (Spoiler: IE!).

Das Schatten-DOM ist im Grunde ein “DOM innerhalb eines DOM” oder ein abgekapselter DOM-Baum, der an das Element angehängt, aber vom Rest getrennt ist. Dieser abgekapselte Teilbaum wird als Schattenbaum bezeichnet. Das Element, an welches er angehängt ist, ist sein Schattenhost. Alles, was man “im Schatten” hinzufügt, ist nur für das Hosting-Element einsehbar, einschließlich . Auf diese Weise ermöglich Shadow-DOM das Kapseln von CSS-Stylen.

Es ist jedoch noch nicht alles. Ein weiteres wichtiges Konzept rund um DOM ist…

Virtuelles DOM

Beginnen wir mit einem einfachen Anwendungsfall, um die Vorteile des virtuellen DOMs (VDOM) zu verstehen. Der Benutzer klickt auf einen Button. Dabei soll ein Menü angezeigt (re-render()), der Hintergrund anders gefärbt (re-render-again()), bestimmte Informationen hervorgehoben (uff-re-render-again()) und irrelevante Informationen ausgeblendet werden (wirklich-wieder-rendern?!()). Da Rendering-Algorithmen aktuell eine Komplexität in der Größenordnung von O(n3) aufweisen, ist dies eine Menge Arbeit. Im Fall von Single Page Applications (SPAs) wird es noch schlimmer, da noch mehr Pixel hin- und hergeschoben werden müssen. Nun kommt das virtuelle DOM ins Spiel. Im Gegensatz zum DOM oder zum Schatten-DOM, ist das virtuelle DOM keine offizielle Spezifikation, sondern eine Methode der Interaktion mit dem DOM, so dass er effizienter aktualisiert werden kann. Ein virtuelles DOM ist ein reguläres Javascript-Objekt. Es kann als Kopie des originalen DOMs betrachtet werden. Diese Kopie kann jederzeit bearbeitet und aktualisiert werden, ohne die DOM-APIs zu verwenden. Sobald alle Aktualisierungen am virtuellen DOM vorgenommen wurden, können wir die beiden abgleichen und feststellen, welche spezifischen Änderungen am ursprünglichen DOM vorgenommen werden müssen (a.k.a. diffing), und sie gezielt und optimiert vornehmen. Das virtuelle DOM ist jedoch keine ultimative Waffe. Z.B. muss React bei jeder render()-Operation ein neues VDOM erstellen und (fast) die gesamte App erneut ausführen, um Unterschiede zu identifizieren. Wenn dies mit resource-intensiven Berechnungen verbunden ist, lohnt sich der Leistungsgewinn durch VDOM-Abstraktion nicht mehr. Weitere Argumente für und gegen den VDOM-Ansatz findet ihr hier und hier.

Weiterführende Infos zum Thema:

Schauen wir uns nun eine Alternative an - das inkrementelle DOM…

Inkrementelles DOM

Wie könnten wir die Fallstricke des virtuellen DOM vermeiden? Indem wir ganz genau wissen, was sich geändert hat und wo. Dann könnten wir nämlich die betroffene Stelle punktuell aktualisieren. Wie wäre es mit einer Vorlage, in der vermerkt ist, was sich überhaupt ändern kann? Dann wüssten wir ja, wo nach Änderungen gesucht werden muss, anstatt das gesamte Dokument zu scannen. Die Vor- und Nachteile dieses Ansatzes werden in der folgenden Diskussion aufgelistet. Der nächste Schritt in diese Richtung ist die Einführung des inkrementellen DOM. Die Grundidee lautet: Jedes DOM-Element stellt Anweisungen zum Rendern und Aktualisieren dar. Es ist keine zwischengeschaltete Abstraktion erforderlich, denn die Anweisungen werden nicht von der Rendering-Engine des Frameworks interpretiert. Sie sind die Rendering-Engine. Diese Anweisungen generieren DOM-Bäume, ermöglichen das Iterieren und Aktualisieren an Ort und Stelle, wenn sich die Daten ändern (mit diesem Ansatz wissen wir ja, was und wo sich geändert hat!). Die inkrementelle Natur ermöglicht einen erheblich reduzierten Speicherverbrauch beim Re-Rendering. Dies ist besonders relevant für Smartphones / andere Geräte mit eingeschränkten Ressourcen. 2015 eingeführt, ist das inkrementelle DOM zwar kein neuer Begriff, aber es könnte mehr Aufmerksamkeit erhalten, nachdem es Teil von Angular Ivy geworden ist.

Weitere Informationen zum Thema:

Über den Tellerrand hinaus denken

  • DOM kann auch XML-Dokumente darstellen.
  • DOM als Standard ist nur eine Empfehlung. Verschiedene Layout-Engines berücksichtigen sie bei der Implementierung in unterschiedlichem Maße. Darüber hinaus kann DOM durch proprietäre Erweiterungen wie Element.scrollIntoViewIfNeeded() erweitert werden. Sie können das aktuelle Element in den sichtbaren Bereich des Fensters scrollen, sofern es nicht bereits darin enthalten ist. Diese Funktion wird jedoch von einigen Browsern nicht unterstützt (Überraschung, Überraschung!).
  • DOM ist kein JavaScript-spezifisches Konzept und wurde bereits in einer Reihe anderer Sprachen implementiert. Das für Webentwickler relevante DOM wird jedoch in ECMA-Script implementiert und besteht hauptsächlich aus JavaScript.
  • Es gibt nicht nur DOM, sondern auch CSSOM (oder vielleicht bald CSS Typed OM) - aber das ist eine andere Geschichte.