Document Object Model (DOM)
Das Document Object Model (DOM) verbindet Webseiten mit Skripten oder Programmiersprachen, indem es die Struktur eines Dokuments, wie das HTML, das eine Webseite darstellt, im Arbeitsspeicher abbildet. Normalerweise 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 Zweig des Baums endet in einem Knoten und jeder Knoten enthält Objekte. DOM-Methoden ermöglichen den programmierten Zugriff auf den Baum. Mit ihnen kann die Struktur, das Styling oder der Inhalt des Dokuments geändert werden.
An Knoten können auch Ereignishandler angehängt werden. Sobald ein Ereignis ausgelöst wird, werden die Ereignishandler ausgeführt.
Konzepte und Nutzung
Das Document Object Model (DOM) ist eine Programmierschnittstelle für Webdokumente. Es stellt die Seite so dar, dass Programme die Dokumentstruktur, das Styling 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 betrachtet werden kann. In beiden Fällen handelt es sich um dasselbe Dokument, aber die Repräsentation durch das Document Object Model (DOM) erlaubt Manipulationen. Als objektorientierte Darstellung der Webseite kann es mit einer Skriptsprache wie JavaScript modifiziert werden.
Beispielsweise gibt das DOM an, dass die Methode querySelectorAll
in diesem Code-Schnipsel 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. Zum Beispiel ist das document
-Objekt, das das Dokument selbst darstellt, jedes table
-Objekt, das die DOM-Schnittstelle HTMLTableElement
für den Zugriff auf HTML-Tabellen implementiert, und so weiter, sind alles Objekte.
Das DOM wird mithilfe mehrerer APIs aufgebaut, die zusammenarbeiten. Das Kern-DOM definiert die Entitäten, die jedes Dokument und die darin enthaltenen Objekte beschreiben. Dies wird bei Bedarf von anderen APIs erweitert, die neue Funktionen und Fähigkeiten zum DOM hinzufügen. Beispielsweise fügt 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 DOM-Baum-Repräsentation. Zum Beispiel betrachten Sie das folgende 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 so aussieht:
Obwohl der obige Baum dem DOM-Baum des Dokumentes ähnelt, sind sie nicht identisch, da der tatsächliche DOM-Baum Leerzeichen bewahrt.
Wenn ein Webbrowser ein HTML-Dokument parst, baut er einen DOM-Baum auf und verwendet diesen dann zur Darstellung des Dokuments.
DOM und JavaScript
Das vorherige kurze Beispiel, wie fast alle Beispiele, ist JavaScript. Das heißt, es ist in JavaScript geschrieben, 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 Konzept von Webseiten, HTML-Dokumenten, SVG-Dokumenten und deren Bestandteilen. Das Dokument als Ganzes, der Kopf, Tabellen im Dokument, Tabellenüberschriften, Text in den Tabellenzellen und alle anderen Elemente in einem Dokument sind Teile des Dokument-Objektmodells für dieses Dokument. Sie können alle mit dem DOM und einer Skriptsprache wie JavaScript abgerufen und manipuliert werden.
Das DOM ist nicht Teil der JavaScript-Sprache, sondern stattdessen 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 eine andere Reihe von APIs, und die DOM-API ist kein Kernbestandteil der Node.js-Laufzeit.
Das DOM wurde entworfen, um unabhängig von einer bestimmten Programmiersprache zu sein, wodurch die strukturelle Darstellung des Dokuments über eine einheitliche API verfügbar ist. Auch wenn die meisten Webentwickler das DOM nur über JavaScript verwenden, können Implementierungen des DOM für jede Sprache erstellt werden, wie dieses Python-Beispiel zeigt:
# 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 darüber, welche Technologien beim Schreiben von JavaScript im Web beteiligt sind, sehen Sie JavaScript-Technologieübersicht.
Zugriff auf das DOM
Sie müssen nichts Besonderes tun, um mit der Nutzung des DOM zu beginnen. Sie verwenden die API direkt in JavaScript aus einem sogenannten Script, einem Programm, das von einem Browser ausgeführt wird.
Wenn Sie ein Skript erstellen, ob inline in einem <script>
-Element oder in der Webseite enthalten, 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 auf der Webseite zu manipulieren (die Nachfolgeelemente des Dokuments). Ihre Programmierung des DOM kann so einfach sein wie das folgende Beispiel, das eine Nachricht auf der Konsole mit der Funktion console.log()
anzeigt:
<body onload="console.log('Welcome to my home page!');">
…
</body>
Da es im Allgemeinen nicht empfohlen wird, die Struktur der Seite (geschrieben in HTML) und die Manipulation des DOM (geschrieben in JavaScript) zu vermischen, werden die JavaScript-Teile hier zusammengefasst und vom HTML getrennt.
Beispielsweise 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 im DOM-Core-Standard definierten Schnittstellen:
AbortController
AbortSignal
AbstractRange
Attr
CDATASection
CharacterData
Comment
CustomEvent
Document
DocumentFragment
DocumentType
DOMError
VeraltetDOMException
DOMImplementation
DOMParser
DOMTokenList
Element
Event
EventTarget
HTMLCollection
MutationObserver
MutationRecord
NamedNodeMap
Node
NodeIterator
NodeList
ProcessingInstruction
QuotaExceededError
Range
ShadowRoot
StaticRange
Text
TreeWalker
XMLDocument
XPathEvaluator
XPathExpression
XPathResult
XSLTProcessor
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 dafür verwirrend sein kann. Zum Beispiel erhält das Objekt, das das HTML form
-Element repräsentiert, seine name
-Eigenschaft von der HTMLFormElement
-Schnittstelle, aber seine className
-Eigenschaft von der HTMLElement
-Schnittstelle. In beiden Fällen befindet sich die gewünschte Eigenschaft in diesem Formularobjekt.
Aber die Beziehung zwischen Objekten und den Schnittstellen, die sie im DOM implementieren, kann verwirrend sein, und dieser Abschnitt versucht, ein wenig über die tatsächlichen Schnittstellen im DOM-Standard und deren Verfügbarkeit zu sagen.
Schnittstellen und Objekte
Viele Objekte implementieren mehrere verschiedene Schnittstellen. Das Tabellenobjekt zum Beispiel implementiert eine spezialisierte HTMLTableElement
Schnittstelle, die solche Methoden wie createCaption
und insertRow
umfasst. Aber da es auch ein HTML-Element ist, implementiert table
die in der DOM-Referenz beschriebenen Element
-Schnittstelle. Und da ein HTML-Element im Bereich des DOM auch ein Knoten im Baum der Knoten ist, die das Objektmodell für eine HTML- oder XML-Seite bilden, implementiert das Tabellenobjekt auch die grundlegendere Node
-Schnittstelle, von der Element
abgeleitet ist.
Wenn Sie auf ein table
-Objekt zugreifen, wie im folgenden Beispiel, verwenden Sie routinemäßig alle drei dieser Schnittstellen austauschbar auf dem Objekt, vielleicht 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";
Fundamentale Datentypen
Diese Seite versucht, die verschiedenen Objekte und Typen in einfachen Begriffen zu beschreiben. Aber es gibt eine Reihe unterschiedlicher Datentypen, die innerhalb der API übergeben werden und denen Sie sich bewusst sein sollten.
Hinweis: Da sich der Großteil des Codes, der das DOM verwendet, auf die Manipulation von HTML-Dokumenten konzentriert, ist es üblich, sich auf die Knoten im DOM als Elemente zu beziehen, 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 gibt das
document zurück, zu dem es gehört), 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 befindliche Objekt ist eine Art von 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 . Es 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
Methode [`document.createElement()`](/de/docs/Web/API/Document/createElement) eine
Objektreferenz 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 sowie die grundlegendere
Node -Schnittstelle, die beide zusammen in diesem
Referenz enthalten sind. In einem HTML-Dokument werden Elemente durch die
HTML-DOM-API
[`HTMLElement`](/de/docs/Web/API/HTMLElement)-Schnittstelle weiter verbessert sowie
andere Schnittstellen, die Fähigkeiten bestimmter 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 Objektreferenz, die
eine spezielle (wenn auch kleine) Schnittstelle für Attribute verfügt. Attribute
sind Knoten im DOM, genau wie Elemente, obwohl Sie sie vielleicht selten
als solche verwenden.
|
Es gibt auch einige allgemeine terminologische Überlegungen zu beachten. Es ist üblich, sich auf jeden Attr
-Knoten als Attribut
zu beziehen und auf ein Array von DOM-Knoten als nodeList
. Sie werden feststellen, dass diese und andere Begriffe in der gesamten Dokumentation eingeführt und verwendet werden.
Die document
- und window
-Objekte sind die Objekte, deren Schnittstellen Sie bei der Programmierung im DOM im Allgemeinen am häufigsten verwenden. Einfach ausgedrückt, repräsentiert das window
-Objekt etwas Ähnliches 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 einzelnen Elementen verwenden. Diese Elemente können auch spezifische Schnittstellen haben, um mit den Daten umzugehen, die diese Elemente enthalten, wie im table
-Objekt-Beispiel im vorhergehenden Abschnitt.
Veraltete DOM-Schnittstellen
Das Document Object Model wurde stark vereinfacht. Um dies zu erreichen, wurden die folgenden Schnittstellen in den verschiedenen DOM-Level-3- oder früheren Spezifikationen entfernt. Sie stehen Webentwicklern nicht mehr zur Verfügung.
DOMConfiguration
DOMErrorHandler
DOMImplementationList
DOMImplementationRegistry
DOMImplementationSource
DOMLocator
DOMObject
DOMSettableTokenList
DOMUserData
ElementTraversal
Entity
EntityReference
NameList
Notation
TypeInfo
UserDataHandler
HTML DOM
Ein Dokument, das HTML enthält, wird mit der Document
-Schnittstelle beschrieben, die durch die HTML-Spezifikation erweitert wird, um verschiedene HTML-spezifische Funktionen zu umfassen. Insbesondere wird die Element
-Schnittstelle verbessert zu HTMLElement
und verschiedenen Unterklassen, die jeweils eines (oder eine Familie von eng verwandten) Elementen repräsentieren.
Die HTML-DOM-API bietet Zugriff auf verschiedene Browser-Funktionen wie Tabs und Fenster, CSS-Stile und Stylesheets, Browserverlauf usw. Diese Schnittstellen werden im HTML DOM API-Dokumentation weiter erörtert.
SVG DOM
Ähnlich wird ein Dokument mit SVG auch unter Verwendung der Document
-Schnittstelle beschrieben, die durch die SVG-Spezifikation erweitert wird, um verschiedene SVG-spezifische Funktionen zu umfassen. Insbesondere wird die Element
-Schnittstelle verbessert zu SVGElement
und verschiedenen Unterklassen, die jeweils ein Element oder eine Familie von eng verwandten Elementen darstellen. Diese Schnittstellen werden in der SVG API-Dokumentation weiter erörtert.
Beispiele
>Textinhalt 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, löschen 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 löschen.
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.body.querySelector(".story");
const setText = document.body.querySelector("#set-text");
setText.addEventListener("click", () => {
story.textContent = "It was a dark and stormy night...";
});
const clearText = document.body.querySelector("#clear-text");
clearText.addEventListener("click", () => {
story.textContent = "";
});
Ergebnis
Ein Kindelement 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 Kindelement. 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.body.querySelector(".parent");
const addChild = document.body.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.body.querySelector("#remove-child");
removeChild.addEventListener("click", () => {
const child = document.body.querySelector(".child");
parent.removeChild(child);
});
Ergebnis
Den Baum lesen und ändern
Angenommen, der Autor möchte die Kopfzeile des Dokuments in Was ist ein DOM-Baum? ändern und zwei Absätze anstelle von einem schreiben. Das folgende Skript würde dies tun:
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);
});
Einen Baum erstellen
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);
Ereignisweiterleitung
Dieses Beispiel zeigt, wie Ereignisse im DOM auf einfache Weise ausgelöst und behandelt werden. Wenn der BODY dieses HTML-Dokuments geladen wird, wird ein Ereignislistener an der obersten Reihe der TABLE registriert. Der Ereignislistener 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 Ereignisobjektmethode auf, event.stopPropagation
, die das Ereignis daran hindert, weiter in das DOM aufzusteigen. Beachten Sie, dass die Tabelle selbst einen onclick
-Ereignishandler hat, der eine Nachricht anzeigen sollte, wenn die Tabelle angeklickt wird. Aber die stopEvent-Methode hat die Propagation gestoppt, und so endet die Ereignisphase effektiv, nachdem die Daten in der Tabelle aktualisiert wurden, und ein Hinweisfenster wird angezeigt, um dies zu bestätigen.
<table id="t-daddy">
<tr id="tbl1">
<td id="c1">one</td>
</tr>
<tr>
<td id="c2">two</td>
</tr>
</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");
});
Anzeige 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 zur Verwendung einer for...in
-Schleife zur Iteration über die Eigenschaften eines Objekts, um deren Werte zu erhalten.
Die Eigenschaften von Ereignisobjekten unterscheiden sich stark zwischen Browsern, der WHATWG-DOM-Standard listet die Standardeigenschaften auf, aber viele Browser haben diese erheblich erweitert.
Legen Sie den folgenden Code in eine leere Textdatei und laden Sie sie in verschiedene Browser, Sie werden überrascht sein über die unterschiedlichen Anzahl und Namen von Eigenschaften. Sie möchten vielleicht auch einige Elemente auf der Seite hinzufügen und diese Funktion von verschiedenen Ereignishandlern 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
Specification |
---|
DOM> |