Document Object Model (DOM)
Das Document Object Model (DOM) verbindet Webseiten mit Skripten oder Programmiersprachen, indem es die Struktur eines Dokuments, wie das HTML für eine Webseite, im Speicher darstellt. In der Regel bezieht es sich auf JavaScript, obwohl das Modellieren von HTML-, SVG- oder XML-Dokumenten als Objekte nicht Teil der Kern-JavaScript-Sprache ist.
Das DOM stellt ein Dokument als einen logischen Baum dar. Jeder Ast des Baums endet in einem Knoten, und jeder Knoten enthält Objekte. DOM-Methoden ermöglichen den programmatischen Zugriff auf den Baum. Damit können Sie die Struktur, den Stil oder den Inhalt des Dokuments ändern.
Knoten können auch Ereignishandler zugewiesen bekommen. Sobald ein Ereignis ausgelöst wird, werden die Ereignishandler ausgeführt.
Konzepte und Anwendung
Das Document Object Model (DOM) ist eine Programmier-Schnittstelle für Webdokumente. Es stellt die Seite so dar, dass Programme die Dokumentstruktur, den Stil und den Inhalt ändern können. Das DOM stellt das Dokument als Knoten und Objekte dar; auf diese Weise können Programmiersprachen mit der Seite interagieren.
Eine Webseite ist ein Dokument, das entweder im Browserfenster angezeigt oder als HTML-Quelle dargestellt werden kann. In beiden Fällen ist es dasselbe Dokument, aber die Darstellung durch das Document Object Model (DOM) ermöglicht es, es zu manipulieren. Als objektorientierte Darstellung der Webseite kann es mit einer Skriptsprache wie JavaScript geändert werden.
Zum Beispiel gibt das DOM an, dass die querySelectorAll-Methode in diesem Code-Snippet eine Liste aller <p>-Elemente im Dokument zurückgeben muss:
const paragraphs = document.querySelectorAll("p");
// paragraphs[0] is the first <p> element
// paragraphs[1] is the second <p> element, etc.
alert(paragraphs[0].nodeName);
Alle Eigenschaften, Methoden und Ereignisse, die zum Manipulieren und Erstellen von Webseiten verfügbar sind, sind in Objekte organisiert. Beispielsweise das document-Objekt, das das Dokument selbst darstellt, oder table-Objekte, die die HTMLTableElement DOM-Schnittstelle zum Zugriff auf HTML-Tabellen implementieren, und so weiter, sind alle Objekte.
Das DOM wird durch mehrere APIs gebaut, die zusammenarbeiten. Das Kern-DOM definiert die Entitäten, die ein Dokument und die Objekte darin beschreiben. Dies wird je nach Bedarf durch andere APIs erweitert, die dem DOM neue Funktionen und Fähigkeiten hinzufügen. So fügt zum Beispiel die HTML DOM API Unterstützung für die Darstellung von HTML-Dokumenten zum Kern-DOM hinzu, und die SVG-API fügt Unterstützung für die Darstellung von SVG-Dokumenten hinzu.
Was ist ein DOM-Baum?
Ein DOM-Baum ist eine Baumstruktur, deren Knoten den Inhalt eines HTML- oder XML-Dokuments darstellen. Jedes HTML- oder XML-Dokument hat eine Darstellung als DOM-Baum. Betrachten Sie zum Beispiel folgendes Dokument:
<html lang="en">
<head>
<title>My Document</title>
</head>
<body>
<h1>Header</h1>
<p>Paragraph</p>
</body>
</html>
Es hat einen DOM-Baum, der wie folgt aussieht:

Obwohl der obige Baum dem DOM-Baum des oben gezeigten Dokuments ähnlich ist, sind sie nicht identisch, da der tatsächliche DOM-Baum Leerzeichen bewahrt.
Wenn ein Webbrowser ein HTML-Dokument parst, erstellt er einen DOM-Baum und verwendet ihn dann, um das Dokument anzuzeigen.
DOM und JavaScript
Das vorherige kurze Beispiel, wie fast alle Beispiele, ist JavaScript. Das heißt, es ist geschrieben in JavaScript, aber verwendet das DOM, um auf das Dokument und seine Elemente zuzugreifen. Das DOM ist keine Programmiersprache, aber ohne es hätte die JavaScript-Sprache kein Modell oder Verständnis für Webseiten, HTML-Dokumente, SVG-Dokumente und ihre Bestandteile. Das gesamte Dokument, der Kopf, die Tabellen im Dokument, Tabellenüberschriften, Text innerhalb der Tabellenzellen und alle anderen Elemente in einem Dokument sind Teile des Document Object Models dieses Dokuments. Sie alle können mit dem DOM und einer Skriptsprache wie JavaScript zugegriffen und manipuliert werden.
Das DOM ist kein Bestandteil der JavaScript-Sprache, sondern eine Web-API, die zum Erstellen von Websites verwendet wird. JavaScript kann auch in anderen Kontexten verwendet werden. Zum Beispiel führt Node.js JavaScript-Programme auf einem Computer aus, bietet jedoch einen anderen Satz von APIs, und die DOM-API ist kein Kernelement der Node.js-Laufzeitumgebung.
Das DOM wurde entworfen, um unabhängig von einer bestimmten Programmiersprache zu sein, und stellt eine strukturelle Darstellung des Dokuments durch eine einzige, konsistente API bereit. Auch wenn die meisten Webentwickler das DOM nur durch JavaScript nutzen werden, können Implementierungen des DOM für jede Sprache erstellt werden, wie dieses Python-Beispiel demonstriert:
# Python DOM example
import xml.dom.minidom as m
doc = m.parse(r"C:\Projects\Py\chap1.xml")
doc.nodeName # DOM property of document object
p_list = doc.getElementsByTagName("para")
Für weitere Informationen über die Technologien, die beim Schreiben von JavaScript im Web involviert sind, siehe JavaScript-Technologieübersicht.
Zugriff auf das DOM
Sie müssen nichts Besonderes unternehmen, um das DOM zu verwenden. Sie verwenden die API direkt in JavaScript von innerhalb eines Scripts, einem Programm, das von einem Browser ausgeführt wird.
Wenn Sie ein Script erstellen, sei es inline in einem <script>-Element oder in die Webseite eingefügt, können Sie sofort beginnen, die API für die document- oder window-Objekte zu verwenden, um das Dokument selbst oder eines der verschiedenen Elemente in der Webseite (die nachfolgenden Elemente des Dokuments) zu manipulieren. Ihr DOM-Programm könnte so einfach sein wie das folgende Beispiel, das eine Nachricht in der Konsole anzeigt, indem es die console.log()-Funktion verwendet:
<body onload="console.log('Welcome to my home page!');">
…
</body>
Es wird im Allgemeinen nicht empfohlen, die Struktur der Seite (geschrieben in HTML) und die Manipulation des DOM (geschrieben in JavaScript) zu vermischen. Daher werden die JavaScript-Teile hier zusammengefasst und vom HTML getrennt.
Zum Beispiel erstellt die folgende Funktion ein neues h1-Element, fügt diesem Element Text hinzu und fügt es dann dem Baum des Dokuments hinzu:
<html lang="en">
<head> </head>
<body>
<script>
// create a couple of elements in an otherwise empty HTML page
const heading = document.createElement("h1");
const headingText = document.createTextNode("Big Head!");
heading.appendChild(headingText);
document.body.appendChild(heading);
</script>
</body>
</html>
DOM-Schnittstellen
Die folgenden sind alle Schnittstellen, die durch die DOM-Spezifikation definiert sind:
AbortControllerAbortSignalAbstractRangeAttrCDATASectionCharacterDataCommentCustomEventDocumentDocumentFragmentDocumentTypeDOMErrorVeraltetDOMExceptionDOMImplementationDOMParserDOMTokenListElementEventEventTargetHTMLCollectionMutationObserverMutationRecordNamedNodeMapNodeNodeIteratorNodeListProcessingInstructionQuotaExceededErrorRangeShadowRootStaticRangeTextTreeWalkerXMLDocumentXPathEvaluatorXPathExpressionXPathResultXSLTProcessor
Dieser Leitfaden behandelt die Objekte und die tatsächlichen Dinge, die Sie verwenden können, um die DOM-Hierarchie zu manipulieren. Es gibt viele Punkte, an denen das Verständnis, wie diese funktionieren, verwirrend sein kann. Zum Beispiel erhält das Objekt, das das HTML-form-Element repräsentiert, seine name-Eigenschaft aus der HTMLFormElement-Schnittstelle, aber seine className-Eigenschaft aus der HTMLElement-Schnittstelle. In beiden Fällen ist die Eigenschaft, die Sie wünschen, in diesem Formularobjekt.
Aber die Beziehung zwischen Objekten und den Schnittstellen, die sie im DOM implementieren, kann verwirrend sein, und daher versucht dieser Abschnitt, ein wenig über die tatsächlichen Schnittstellen in der DOM-Spezifikation und deren Bereitstellung zu erklären.
Schnittstellen und Objekte
Viele Objekte implementieren mehrere verschiedene Schnittstellen. Das Tabellenobjekt implementiert beispielsweise eine spezialisierte HTMLTableElement-Schnittstelle, die Methoden wie createCaption und insertRow umfasst. Da es sich aber auch um ein HTML-Element handelt, implementiert table die Element-Schnittstelle, die im DOM-Referenzkapitel Element beschrieben wird. Und letztendlich, da ein HTML-Element auch, soweit es das DOM betrifft, ein Knoten im Baum der Knoten ist, die das Objektmodell einer HTML- oder XML-Seite ausmachen, implementiert das Tabellenobjekt auch die einfachere Node-Schnittstelle, von der Element abgeleitet ist.
Wenn Sie eine Referenz zu einem table-Objekt erhalten, wie im folgenden Beispiel, verwenden Sie routinemäßig alle drei dieser Schnittstellen abwechselnd auf dem Objekt, möglicherweise ohne es zu wissen.
const table = document.getElementById("table");
const tableAttrs = table.attributes; // Node/Element interface
for (const attr of tableAttrs) {
// HTMLTableElement interface: border attribute
if (attr.nodeName.toLowerCase() === "border") {
table.border = "1";
}
}
// HTMLTableElement interface: summary attribute
table.summary = "note: increased border";
Grundlegende Datentypen
Diese Seite versucht, die verschiedenen Objekte und Typen in einfachen Begriffen zu beschreiben. Es gibt jedoch eine Reihe von verschiedenen Datentypen, die in der API übergeben werden, die Ihnen bewusst sein sollten.
Hinweis: Da der überwiegende Teil des Codes, der das DOM verwendet, sich um die Manipulation von HTML-Dokumenten dreht, ist es üblich, auf die Knoten im DOM als Elemente zu verweisen, obwohl streng genommen nicht jeder Knoten ein Element ist.
Die folgende Tabelle beschreibt diese Datentypen kurz.
| Datentyp (Schnittstelle) | Beschreibung |
|---|---|
| [`Document`](/de/docs/Web/API/Document) |
Wenn ein Mitglied ein Objekt vom Typ document zurückgibt (z. B. die
ownerDocument-Eigenschaft eines Elements das document, zu dem es gehört, zurückgibt), ist dieses Objekt das Wurzel-
document-Objekt selbst. Das
DOM document Referenz
Kapitel beschreibt das document-Objekt.
|
| [`Node`](/de/docs/Web/API/Node) | Jedes im Dokument lokalisierte Objekt ist eine Art Knoten. In einem HTML-Dokument kann ein Objekt ein Elementknoten, aber auch ein Textknoten oder Attributknoten sein. |
| [`Element`](/de/docs/Web/API/Element) |
Der element-Typ basiert auf node. Er bezieht sich
auf ein Element oder einen Knoten vom Typ element, der von einem
Mitglied der DOM-API zurückgegeben wird. Anstatt zum Beispiel zu sagen, dass die
[`document.createElement()`](/de/docs/Web/API/Document/createElement)-Methode ein
Objekt-Referenz zu einem node zurückgibt, sagen wir einfach, dass diese Methode
das element zurückgibt, das gerade im DOM erstellt wurde.
element-Objekte implementieren die DOM
Element-Schnittstelle und auch die einfachere
Node-Schnittstelle, die beide zusammen in dieser
Referenz enthalten sind. In einem HTML-Dokument werden Elemente weiter durch
die [`HTMLElement`](/de/docs/Web/API/HTMLElement)-Schnittstelle der HTML DOM-API sowie durch
andere Schnittstellen beschrieben, die Fähigkeiten spezifischer Arten von Elementen
beschreiben (zum Beispiel, [`HTMLTableElement`](/de/docs/Web/API/HTMLTableElement) für
<table>-Elemente).
|
| [`Attr`](/de/docs/Web/API/Attr) |
Wenn ein attribute von einem Mitglied zurückgegeben wird (z. B. durch die
createAttribute()-Methode), ist es eine Objekt-Referenz, die
eine spezielle (wenn auch kleine) Schnittstelle für Attribute offenlegt. Attribute
sind Knoten im DOM genau wie Elemente, obwohl Sie sie selten als solche verwenden
werden.
|
Es gibt auch einige allgemeine Überlegungen zur Terminologie, die Sie berücksichtigen sollten. Es ist zum Beispiel üblich, auf jeden Attr-Knoten als attribute zu verweisen und auf ein Array von DOM-Knoten als nodeList. Sie werden feststellen, dass diese Begriffe und andere in der Dokumentation eingeführt und verwendet werden.
Die document- und window-Objekte sind die Objekte, deren Schnittstellen Sie in der DOM-Programmierung am häufigsten verwenden. Kurz gesagt, das window-Objekt repräsentiert etwas wie den Browser und das document-Objekt ist die Wurzel des Dokuments selbst. Element erbt von der generischen Node-Schnittstelle und zusammen bieten diese beiden Schnittstellen viele der Methoden und Eigenschaften, die Sie auf einzelne Elemente anwenden. Diese Elemente können auch spezifische Schnittstellen haben, die sich mit der Art von Daten befassen, die diese Elemente enthalten, wie im Tabellenobjekts-Beispiel im vorherigen Abschnitt.
Veraltete DOM-Schnittstellen
Das Document Object Model wurde stark vereinfacht. Um dies zu erreichen, wurden die folgenden Schnittstellen in den verschiedenen Spezifikationen der DOM-Ebene 3 oder früher entfernt. Sie stehen Webentwicklern nicht mehr zur Verfügung.
DOMConfigurationDOMErrorHandlerDOMImplementationListDOMImplementationRegistryDOMImplementationSourceDOMLocatorDOMObjectDOMSettableTokenListDOMUserDataElementTraversalEntityEntityReferenceNameListNotationTypeInfoUserDataHandler
HTML DOM
Ein Dokument, das HTML enthält, wird durch die Document-Schnittstelle beschrieben, die durch die HTML-Spezifikation erweitert wird, um verschiedene HTML-spezifische Funktionen zu umfassen. Insbesondere wird die Element-Schnittstelle verbessert, um HTMLElement und verschiedene Unterklassen zu werden, von denen jede eines (oder eine Familie von eng verwandten) Elementen darstellt.
Die HTML DOM API bietet Zugang zu verschiedenen Browser-Funktionen wie Tabs und Fenstern, CSS-Stilen und Stylesheets, Browser-Historie usw. Diese Schnittstellen werden weiter in der HTML DOM API-Dokumentation behandelt.
SVG DOM
Ebenso wird ein Dokument, das SVG enthält, auch durch die Document-Schnittstelle beschrieben, die durch die SVG-Spezifikation erweitert wird, um verschiedene SVG-spezifische Funktionen zu umfassen. Insbesondere wird die Element-Schnittstelle verbessert, um SVGElement und verschiedene Unterklassen zu werden, von denen jede ein Element oder eine Familie von eng verwandten Elementen darstellt. Diese Schnittstellen werden weiter in der SVG API-Dokumentation behandelt.
Beispiele
>Texteinhalt festlegen
Dieses Beispiel verwendet ein <div>-Element, das ein <textarea> und zwei <button>-Elemente enthält. Wenn der Benutzer auf den ersten Button klickt, setzen wir etwas Text im <textarea>. Wenn der Benutzer auf den zweiten Button klickt, leeren wir den Text. Wir verwenden:
Document.querySelector(), um auf das<textarea>und den Button zuzugreifenEventTarget.addEventListener(), um auf Buttonklicks zu lauschenNode.textContent, um den Text zu setzen und zu leeren.
HTML
<div class="container">
<textarea class="story"></textarea>
<button id="set-text" type="button">Set text content</button>
<button id="clear-text" type="button">Clear text content</button>
</div>
CSS
.container {
display: flex;
gap: 0.5rem;
flex-direction: column;
}
button {
width: 200px;
}
JavaScript
const story = document.querySelector(".story");
const setText = document.querySelector("#set-text");
setText.addEventListener("click", () => {
story.textContent = "It was a dark and stormy night...";
});
const clearText = document.querySelector("#clear-text");
clearText.addEventListener("click", () => {
story.textContent = "";
});
Ergebnis
Ein Kind-Element hinzufügen
Dieses Beispiel verwendet ein <div>-Element, das ein <div> und zwei <button>-Elemente enthält. Wenn der Benutzer auf den ersten Button klickt, erstellen wir ein neues Element und fügen es als Kind des <div> hinzu. Wenn der Benutzer auf den zweiten Button klickt, entfernen wir das Kind-Element. Wir verwenden:
Document.querySelector(), um auf das<div>und die Buttons zuzugreifenEventTarget.addEventListener(), um auf Buttonklicks zu lauschenDocument.createElement, um das Element zu erstellenNode.appendChild(), um das Kind hinzuzufügenNode.removeChild(), um das Kind zu entfernen.
HTML
<div class="container">
<div class="parent">parent</div>
<button id="add-child" type="button">Add a child</button>
<button id="remove-child" type="button">Remove child</button>
</div>
CSS
.container {
display: flex;
gap: 0.5rem;
flex-direction: column;
}
button {
width: 100px;
}
div.parent {
border: 1px solid black;
padding: 5px;
width: 100px;
height: 100px;
}
div.child {
border: 1px solid red;
margin: 10px;
padding: 5px;
width: 80px;
height: 60px;
box-sizing: border-box;
}
JavaScript
const parent = document.querySelector(".parent");
const addChild = document.querySelector("#add-child");
addChild.addEventListener("click", () => {
// Only add a child if we don't already have one
// in addition to the text node "parent"
if (parent.childNodes.length > 1) {
return;
}
const child = document.createElement("div");
child.classList.add("child");
child.textContent = "child";
parent.appendChild(child);
});
const removeChild = document.querySelector("#remove-child");
removeChild.addEventListener("click", () => {
const child = document.querySelector(".child");
parent.removeChild(child);
});
Ergebnis
Lesen und Modifizieren des Baumes
Angenommen, der Autor möchte die Überschrift des Dokuments in Was ist ein DOM-Baum? ändern und zwei Absätze statt eines schreiben. Das folgende Skript würde die Arbeit erledigen:
HTML
<html lang="en">
<head>
<title>My Document</title>
</head>
<body>
<input type="button" value="Change this document." />
<h2>Header</h2>
<p>Paragraph</p>
</body>
</html>
JavaScript
document.querySelector("input").addEventListener("click", () => {
// document.getElementsByTagName("h2") returns a NodeList of the <h2>
// elements in the document, and the first is number 0:
const header = document.getElementsByTagName("h2").item(0);
// The firstChild of the header is a Text node:
header.firstChild.data = "A dynamic document";
// Now header is "A dynamic document".
// Access the first paragraph
const para = document.getElementsByTagName("p").item(0);
para.firstChild.data = "This is the first paragraph.";
// Create a new Text node for the second paragraph
const newText = document.createTextNode("This is the second paragraph.");
// Create a new Element to be the second paragraph
const newElement = document.createElement("p");
// Put the text in the paragraph
newElement.appendChild(newText);
// Put the paragraph on the end of the document by appending it to
// the body (which is the parent of para)
para.parentNode.appendChild(newElement);
});
Erstellen eines Baumes
Sie können den Baum in Was ist ein DOM-Baum? auch vollständig in JavaScript erstellen.
const root = document.createElement("html");
root.lang = "en";
const head = document.createElement("head");
const title = document.createElement("title");
title.appendChild(document.createTextNode("My Document"));
head.appendChild(title);
const body = document.createElement("body");
const header = document.createElement("h1");
header.appendChild(document.createTextNode("Header"));
const paragraph = document.createElement("p");
paragraph.appendChild(document.createTextNode("Paragraph"));
body.appendChild(header);
body.appendChild(paragraph);
root.appendChild(head);
root.appendChild(body);
Ereignisausbreitung
Dieses Beispiel zeigt auf sehr einfache Weise, wie Ereignisse im DOM ausgelöst und gehandhabt werden. Wenn der BODY dieses HTML-Dokuments geladen wird, wird ein Ereignis-Listener auf der obersten Zeile der TABLE registriert. Der Ereignis-Listener behandelt das Ereignis, indem er die Funktion stopEvent ausführt, die den Wert in der unteren Zelle der Tabelle ändert.
stopEvent ruft jedoch auch eine Methode des Ereignisobjekts auf, event.stopPropagation, die das Ereignis daran hindert, weiter im DOM nach oben zu sprudeln. Beachten Sie, dass die Tabelle selbst einen onclick-Ereignishandler hat, der eine Nachricht anzeigen soll, wenn auf die Tabelle geklickt wird. Doch die StopEvent-Methode hat die Ausbreitung gestoppt, und somit wird nach der Aktualisierung der Daten in der Tabelle die Ereignisphase effektiv beendet, und ein Bestätigungsfenster wird angezeigt.
<table id="t-daddy">
<tbody>
<tr id="tbl1">
<td id="c1">one</td>
</tr>
<tr>
<td id="c2">two</td>
</tr>
</tbody>
</table>
#t-daddy {
border: 1px solid red;
}
#c1 {
background-color: pink;
}
function stopEvent(event) {
const c2 = document.getElementById("c2");
c2.textContent = "hello";
// this ought to keep t-daddy from getting the click.
event.stopPropagation();
console.log("event propagation halted.");
}
const elem = document.getElementById("tbl1");
elem.addEventListener("click", stopEvent);
document.getElementById("t-daddy").addEventListener("click", () => {
console.log("t-daddy clicked");
});
Anzeigen von Ereignisobjekteigenschaften
Dieses Beispiel verwendet DOM-Methoden, um alle Eigenschaften des onload-event-Objekts und deren Werte in einer Tabelle anzuzeigen. Es zeigt auch eine nützliche Technik, eine for...in-Schleife zu verwenden, um über die Eigenschaften eines Objekts zu iterieren und deren Werte zu erhalten.
Die Eigenschaften von Ereignisobjekten unterscheiden sich stark zwischen den Browsern, der WHATWG DOM Standard listet die Standard-Eigenschaften auf, jedoch haben viele Browser diese stark erweitert.
Setzen Sie den folgenden Code in eine leere Textdatei und laden Sie sie in verschiedenen Browsern, Sie werden von der unterschiedlichen Anzahl und den Namen der Eigenschaften überrascht sein. Vielleicht möchten Sie auch einige Elemente auf der Seite hinzufügen und diese Funktion von verschiedenen Ereignishandlern aus aufrufen.
<h1>Properties of the DOM <span id="eventType"></span> Event Object</h1>
table {
border-collapse: collapse;
}
thead {
font-weight: bold;
}
td {
padding: 2px 10px;
}
.odd {
background-color: #efdfef;
}
.even {
background-color: white;
}
function showEventProperties(e) {
function addCell(row, text) {
const cell = row.insertCell(-1);
cell.appendChild(document.createTextNode(text));
}
const event = e || window.event;
document.getElementById("eventType").textContent = event.type;
const table = document.createElement("table");
const thead = table.createTHead();
let row = thead.insertRow(-1);
const labelList = ["#", "Property", "Value"];
const len = labelList.length;
for (let i = 0; i < len; i++) {
addCell(row, labelList[i]);
}
const tbody = document.createElement("tbody");
table.appendChild(tbody);
for (const p in event) {
row = tbody.insertRow(-1);
row.className = row.rowIndex % 2 ? "odd" : "even";
addCell(row, row.rowIndex);
addCell(row, p);
addCell(row, event[p]);
}
document.body.appendChild(table);
}
showEventProperties(event);
Spezifikationen
| Spezifikation |
|---|
| DOM> |