Das Document Object Model
AnfängerEinheit 5 von 9 in Kurs: JavaScript – DOM, Ereignisse und asynchroner Code
Was du lernst
- Erkläre, was das Document Object Model ist, wie der Browser es aus HTML aufbaut und wie seine Knoten zusammenhängen, damit du dich auf jeder Seite zurechtfindest.
- Beschreibe das DOM als Baum aus KnotenErkläre, was das DOM ist, wie der Browser es aus HTML aufbaut, welche Arten von Knoten es enthält und wie es sich vom HTML-Quelltext unterscheidet.
- Navigiere von einem Element zu seinem Elternelement, seinen Kindelementen und seinen GeschwisterelementenNavigiere von einem beliebigen Element durch den Baum zu seinen verwandten Knoten, wähle zwischen Eigenschaften mit Textknoten und solchen, die nur Elemente zurückgeben, und finde den nächsten passenden Vorfahrenknoten.
- Beschreibe das DOM als Baum aus Knoten
- Finde mit CSS-Selektoren genau die Elemente, die ein Skript benötigt, behandle fehlende Elemente und arbeite mit Sammlungen passender Elemente.
- Wähle ein einzelnes Element ausFinde ein Element mit querySelector oder getElementById, suche innerhalb eines Teils der Seite und behandle den Fall, dass nichts passt.
- Wähle mehrere Elemente aus und arbeite mit den ErgebnissenWähle alle passenden Elemente aus, durchlaufe die Ergebnisse, wandle sie bei Bedarf in ein Array um und erkenne, wann eine Sammlung sich selbst aktualisiert.
- Wähle ein einzelnes Element aus
- Aktualisiere die Texte von Elementen und die Attribute und Eigenschaften, die sie steuern. Wähle eine sichere Methode für Inhalte von Nutzern oder aus Daten und speichere zusätzliche Daten an Elementen.
- Ändere Text und HTML innerhalb eines ElementsLies und ersetze den Inhalt eines Elements mit textContent, innerText und innerHTML und schütze Seiten vor eingeschleustem Code.
- Lies und setze Attribute und EigenschaftenArbeite mit Attributen über getAttribute und setAttribute sowie mit den zugehörigen Elementeigenschaften und behandle boolesche Attribute und Unterschiede zwischen Attributen und Eigenschaften.
- Speichere Daten an Elementen und lies Formularfelder ausSpeichere zusätzliche Informationen mit Datenattributen an Elementen und lies und setze den aktuellen Wert von Formularfeldern.
- Ändere Text und HTML innerhalb eines Elements
- Schalte CSS-Klassen um, setze Inline-Stile für berechnete Werte, lies die vom Browser angewandten Stile und blende Teile einer Seite ein oder aus.
- Füge CSS-Klassen hinzu, entferne sie und schalte sie umÄndere das Aussehen eines Elements, indem du Klassen mit classList umschaltest und die visuellen Regeln im Stylesheet belässt.
- Setze Inline-Stile und lies berechnete Stile ausSetze Inline-Stile über die Eigenschaft style, wenn ein Wert zur Laufzeit berechnet wird, entferne sie wieder und lies die Stile, die der Browser tatsächlich anwendet.
- Blende Teile einer Seite ein und ausBlende Elemente mit dem Attribut hidden oder einer Klasse aus und wieder ein, wähle zwischen den CSS-Möglichkeiten zum Unsichtbarmachen und halte den Zustand für Screenreader-Nutzer eindeutig.
- Füge CSS-Klassen hinzu, entferne sie und schalte sie um
- Erstelle neue Elemente in JavaScript, platziere sie genau an der richtigen Stelle und entferne, ersetze oder kopiere Elemente, damit sich die Seite ohne Neuladen ändert.
- Erstelle neue Elemente und füge sie einErstelle Elemente mit createElement, fülle sie mit Text und Attributen und füge sie am Ende, am Anfang oder neben einem anderen Element ein.
- Entferne, ersetze und kopiere ElementeEntferne Elemente von der Seite, leere einen Container, ersetze ein Element durch ein anderes und erstelle Kopien mit cloneNode.
- Erstelle neue Elemente und füge sie ein
- Wandle Datenarrays in Listen und Tabellen auf der Seite um, erstelle viele Einträge effizient und halte die Seite bei Änderungen mit den Daten aktuell.
- Erstelle Listeneinträge und Tabellenzeilen aus einem ArrayWandle ein Array aus Objekten mit textContent in Listeneinträge oder Tabellenzeilen um, zeige sinnvolle Ausgaben für leere Listen und fehlende Werte an und verknüpfe jedes Element mit seinen Daten.
- Erstelle viele Elemente effizient mit Dokumentfragmenten und template-ElementenFüge viele neue Elemente mit einem DocumentFragment oder einem einzelnen append in einem Schritt ein und verwende Markup aus einem HTML-template-Element wieder.
- Aktualisiere die Seite, wenn sich die Daten ändernHalte die Daten als einzige Source of Truth, rendere nach jeder Änderung erneut daraus und zeige gefilterte, sortierte und zusammengefasste Ansichten an, ohne die ursprünglichen Daten zu verlieren.
- Erstelle Listeneinträge und Tabellenzeilen aus einem Array
Document Object Model einfach erklärt
1Lies die Seite als Baum
Der Browser wandelt HTML in Objekte um, die JavaScript lesen und ändern kann. Diese Objekte bilden einen Baum. Um ein Seitenelement zu finden, musst du deshalb auch verstehen, wo es sich zwischen den anderen Knoten befindet. Beginne damit, vertraute Tags mit den Objekten im Browser zu verbinden. Verfolge dann die Beziehungen zwischen Eltern-, Kind- und Geschwisterknoten und achte auf die Textknoten, die aus Leerzeichen und Zeilenumbrüchen entstehen. Mit den DevTools kannst du diesen Baum sehen, während dein Code ihn verändert.
1.1 HTML wird zu einem Baum aus Objekten
Das Document Object Model, kurz DOM, ist der dynamische Baum aus Seitenobjekten im Browser. JavaScript liest und ändert diese Objekte, um die Seite ohne Neuladen zu aktualisieren. Der Browser stellt die DOM-API bereit; JavaScript ist die Sprache, mit der sie aufgerufen wird.
Beginne beim Dokument
document ist der Einstiegspunkt. document.documentElement verweist auf <html>, document.head auf <head> und document.body auf <body>. Der Browser-Tab wird durch window repräsentiert, dessen Eigenschaft document auf dieses Dokument verweist.
Jeder Eintrag im Baum ist ein Knoten. Elemente stehen für Tags; Textknoten enthalten Zeichen; Kommentarknoten enthalten HTML-Kommentare; der Dokumentknoten steht über den Elementen der Seite. Ihre nodeType-Werte sind entsprechend 1, 3, 8 und 9. Jedes Element ist ein Knoten, aber Text und Kommentare sind keine Elemente.
Lies die Familienbeziehungen
<ul id="menu"><li>Home</li><li>About</li></ul>
Die Liste ist der Elternknoten zweier Eintragselemente, die Geschwisterknoten sind. Jeder Eintrag ist ihr Kindknoten. Der erste Eintrag hat einen Textknoten als Kindknoten, der „Home“ enthält. Die Liste ist ein Vorfahrenknoten dieses Textknotens und der Text ein Nachfahrenknoten der Liste. Diese Beziehungen beschreiben die Verschachtelung, nicht die Positionen auf dem Bildschirm.
Leerzeichen und Zeilenumbrüche zwischen Tags werden normalerweise zu Textknoten mit Leerraumzeichen. Eine eingerückte Liste kann deshalb zwei Kindelemente, aber mehr als zwei Kindknoten haben. children und firstElementChild geben nur Elemente zurück; childNodes und firstChild schließen Text und Kommentare ein.
Vergleiche den Baum mit dem Quelltext
Beim Parsen wird Markup in den Baum umgewandelt und kann dabei ergänzt oder korrigiert werden. Zeilen, die direkt innerhalb einer <table> stehen, erhalten einen <tbody>-Elternknoten. Fehlende <html>-, <head>- oder <body>-Elemente können ebenfalls ergänzt werden. Wähle aus dem tatsächlichen Baum aus, einschließlich dieser vom Parser hinzugefügten Elemente.
Änderungen durch Skripte betreffen das aktuelle DOM des Browsers, nicht die HTML-Datei auf dem Server. „Seitenquelltext anzeigen“ zeigt das ursprüngliche HTML, während der Bereich „Elemente“ der DevTools den aktuellen Baum zeigt. Beim Neuladen wird das DOM neu aufgebaut; eine Änderung allein speichert die zugrunde liegenden Daten nicht.
Untersuche ein Objekt
Klicke mit der rechten Maustaste auf ein Element und wähle „Untersuchen“. Gib $0 in der Konsole ein, um auf das ausgewählte Element zu verweisen. console.log($0) stellt es als Markup dar; console.dir($0) zeigt seine Eigenschaften. Klappe eine eingerückte Liste auf, um die Leerraumknoten neben ihren Eintragselementen zu sehen.
Wichtige Erkenntnisse
- Das DOM ist ein vom Browser bereitgestellter Baum, den JavaScript lesen und ändern kann.
- Elemente, Text, Kommentare und das Dokument sind verschiedene Arten von Knoten.
- Leerraumzeichen und vom Parser hinzugefügte Elemente können dazu führen, dass sich das DOM vom geschriebenen HTML unterscheidet.
- Untersuche den aktuellen Baum in den DevTools; eine DOM-Änderung schreibt das HTML auf dem Server nicht um.
1.2 Verfolge Eltern-, Kind- und Geschwisterknoten
Über Baumeigenschaften kann ein Skript von einem bereits vorliegenden Element aus benachbarte Inhalte erreichen. Entscheide, ob dieser Pfad Text und Kommentare oder nur Elemente einschließen soll.
Wähle Knoten oder Elemente
Zu den Knoteneigenschaften gehören parentNode, childNodes, firstChild, lastChild, previousSibling und nextSibling. Ihre Gegenstücke für Elemente sind parentElement, children, firstElementChild, lastElementChild, previousElementSibling und nextElementSibling. children ist eine HTMLCollection; childNodes ist eine NodeList.
<ul id="tasks">
<li>Buy milk</li>
<li>Call Sam</li>
</ul>
Hier ist tasks.childNodes.length gleich 5: zwei Elemente und drei Folgen von Leerraumzeichen. tasks.children.length ist gleich 2. tasks.firstChild ist ein Textknoten mit Leerraumzeichen, während tasks.firstElementChild.textContent gleich „Buy milk“ ist. Indizes beginnen bei 0, daher ist tasks.children[1] der zweite Eintrag.
Folge einem kurzen Pfad
const tasks = document.querySelector("#tasks");
const first = tasks.firstElementChild;
const second = first.nextElementSibling;
console.log(second.textContent);
console.log(second.parentElement === tasks);
Die Ausgabe ist „Call Sam“, gefolgt von true. tasks.lastElementChild erreicht denselben Eintrag direkt, ebenso wie tasks.children[tasks.children.length - 1].
Behandle einen fehlenden verwandten Knoten
Das nextElementSibling des letzten Eintrags ist null. Ein Element ohne Kindelemente hat firstElementChild === null und eine leere children-Sammlung. Der parentNode des HTML-Wurzelelements ist das Dokument, sein parentElement ist aber null.
Das Lesen einer Eigenschaft von null löst einen TypeError aus. Prüfe zuerst oder verwende second.nextElementSibling?.textContent, was undefined ergibt, wenn kein nächstes Element existiert.
Finde einen umschließenden Eintrag
closest(selector) prüft das aktuelle Element und dann seine Vorfahrenknoten und gibt den nächsten Treffer oder null zurück. Eine Schaltfläche innerhalb von <li class="task" data-id="7"> kann button.closest(".task") verwenden; die dataset.id des gefundenen Eintrags ist „7“. matches(selector) prüft dagegen nur das aktuelle Element und gibt einen booleschen Wert zurück.
Lange Pfade wie el.parentElement.parentElement.nextElementSibling hängen von der genauen Verschachtelung ab. Ein zusätzliches umschließendes Element ändert ihre Bedeutung. Verwende Selektoren für benannte Bereiche, kurze Navigation für stabile Beziehungen und closest() für einen umschließenden Eintrag.
Wichtige Erkenntnisse
- Verwende die Navigation nur über Elemente, wenn Leerraumzeichen und Kommentare übersprungen werden sollen.
- Sammlungen beginnen bei Index 0; ihre Länge ist eine Anzahl, nicht der letzte Index.
- Ein fehlender verwandter Knoten ist null; prüfe ihn, bevor du daraus liest.
- closest() prüft das Element selbst und danach seine Vorfahrenknoten.
- matches() prüft das aktuelle Element, ohne durch den Baum zu navigieren.
2Finde Seitenelemente
Eine DOM-Änderung beginnt mit einer Referenz auf das richtige Element. Mit CSS-Selektoren kannst du die ganze Seite oder nur einen Container durchsuchen, während du mit Sammlungsmethoden viele Ergebnisse verarbeiten kannst. Der Rückgabewert ist wichtig: Eine Suche kann ein Element oder null liefern, eine andere gibt immer eine Sammlung zurück. Du musst auch wissen, wann das Skript ausgeführt wird und ob sich eine gespeicherte Sammlung bei Änderungen der Seite verändert, denn beides beeinflusst, was dein Code findet.
2.1 Finde ein Element und prüfe das Ergebnis
Ein Selektor macht aus einer Beschreibung eines Elements eine Objektreferenz. Beginne mit der kleinsten Suche, die das benötigte Element identifiziert, und prüfe dann, ob es gefunden wurde, bevor du es änderst.
Suche mit einem CSS-Selektor oder einer ID
document.querySelector(selector) gibt das erste passende Element in Dokumentreihenfolge zurück. Die Methode akzeptiert vertraute CSS-Selektoren: "h1", ".price", "#cart", "nav a" oder 'input[type="email"]'. Wenn nichts passt, gibt sie null zurück.
document.getElementById("cart") sucht direkt nach einer ID. Das Argument ist die ID ohne Zusatz. getElementById("#cart") sucht nach einer ID, die tatsächlich das Rautezeichen enthält, während querySelector("cart") nach einem <cart>-Tag sucht. Verwende querySelector("#cart") für den ID-Selektor.
IDs müssen eindeutig sein. Wenn kopiertes Markup zwei Elementen dieselbe ID gibt, liefern diese Suchen das erste in Dokumentreihenfolge zurück. Korrigiere das doppelte Markup, statt zu erwarten, dass eine ID-Suche die zweite Kopie erreicht.
Suche innerhalb eines Containers
Angenommen, mehrere Karten haben ein Element mit der Klasse name. Wähle zuerst die Profilkarte aus und durchsuche dann ihre Nachfahrenelemente:
const card = document.querySelector("#profile");
if (card) {
const name = card.querySelector(".name");
if (name) name.textContent = "Maya";
}
Die innere Suche ist auf die Profilkarte beschränkt, sodass ein früheres .name an anderer Stelle nicht stört. Der Container selbst kommt bei seiner eigenen querySelector()-Suche nicht als Treffer infrage. Gewöhnliche Elemente unterstützen diese Methode, aber getElementById() gehört zu document.
Unterscheide einen fehlenden Treffer von einem ungültigen Selektor
Eine gültige Suche ohne Treffer ergibt null. Der Versuch, null.textContent zu setzen, löst einen TypeError aus. Sichere daher optionale Inhalte ab:
const banner = document.querySelector(".banner");
if (banner) banner.textContent = "Sale ends Friday";
Ein ungültiger CSS-Selektor löst einen SyntaxError aus, bevor es ein Ergebnis geben kann. Für <p id="1st"> ist querySelector("#1st") ungültig, weil die Ziffer in diesem CSS-ID-Selektor maskiert werden muss. getElementById("1st") verwendet eine ID als Literal und funktioniert direkt.
Führe den Code aus, nachdem das benötigte Markup existiert
Ein klassisches externes Skript im <head> wird ausgeführt, bevor der Browser den Body geparst hat. Eine Suche nach einem späteren Absatz gibt daher null zurück, selbst wenn das HTML ihn enthält. Verwende <script src="app.js" defer></script> für die Ausführung nach dem Parsen, verwende ein Modulskript oder platziere das Skript direkt vor </body>. Modulskripte werden standardmäßig verzögert ausgeführt. Das Attribut defer hat auf ein klassisches Inline-Skript keine Wirkung.
Bei einer HTML-Seite, die mit <!DOCTYPE html> beginnt, wird bei ID- und Klassenselektoren zwischen Groß- und Kleinschreibung unterschieden: .Price passt nicht zu class="price". Bei HTML-Tag-Selektoren wird nicht unterschieden, sodass "LI" und "li" beide zu Listeneinträgen passen. Wenn eine Suche fehlschlägt, prüfe Schreibweise, Selektorsyntax, Suchcontainer und Ausführungszeitpunkt des Skripts.
Wichtige Erkenntnisse
- querySelector() gibt den ersten Treffer oder null zurück.
- getElementById() erwartet eine ID ohne Zusatz; querySelector() erwartet CSS-Selektorsyntax.
- Durchsuche die Nachfahrenelemente eines Containers, wenn eine Klasse in mehreren Seitenbereichen vorkommt.
- Ein fehlender Treffer ergibt null; ungültige Selektorsyntax löst einen Fehler aus.
- Führe DOM-Code aus, nachdem sein Markup geparst wurde.
- Halte IDs eindeutig und achte bei ID- und Klassenselektoren auf Groß- und Kleinschreibung.
2.2 Arbeite mit Sammlungen passender Elemente
Verwende querySelectorAll(), wenn dieselbe Operation auf mehrere Elemente angewendet werden soll. Das Ergebnis ist eine Sammlung. Du musst also entscheiden, wie du sie durchläufst und ob du eine Momentaufnahme oder eine dynamische Ansicht benötigst.
Lies und durchlaufe eine NodeList
document.querySelectorAll(".note") gibt eine NodeList passender Elemente in Dokumentreihenfolge zurück. Ohne Treffer erhältst du eine leere NodeList mit der Länge 0. Die Sammlung selbst ist dennoch ein Truthy-Wert; if (notes) sagt dir nicht, ob sie Elemente enthält. Prüfe notes.length.
Eine NodeList unterstützt Indizes, length, forEach() und for...of, ist aber kein Array und hat kein map(), filter() oder reduce(). Wandle sie um, wenn du diese Methoden benötigst:
const weights = Array.from(document.querySelectorAll(".weight"))
.map(el => Number(el.textContent));
const total = weights.reduce((sum, weight) => sum + weight, 0);
Für Elemente mit „4.5“, „12“ und „3.25“ ist das Array [4.5, 12, 3.25] und die Summe beträgt 19,75 kg. Die Umwandlung in Zahlen ist wichtig, weil die Textwerte Zeichenketten sind.
Eine Sammlung ist kein zusammengefasstes Element. Das Setzen von notes.textContent ändert keine Notiz, und notes.classList.add("saved") löst einen Fehler aus, weil die NodeList keine classList hat. Wende die Änderung auf jedes Element an:
const notes = document.querySelectorAll(".note");
notes.forEach(note => note.classList.add("saved"));
Vergleiche statische und dynamische Ergebnisse
Die NodeList von querySelectorAll() ist statisch: Ihre Zugehörigkeit steht zum Zeitpunkt der Suche fest. Die Elemente, auf die sie verweist, sind weiterhin die tatsächlichen Objekte, sodass sich ihr Text oder ihre Klassen ändern können.
getElementsByClassName("note") und getElementsByTagName("li") geben eine dynamische HTMLCollection zurück. Auch children ist dynamisch. Diese Sammlungen aktualisieren ihre Zugehörigkeit, wenn sich das DOM ändert. Sie unterstützen Indizes und for...of, aber kein forEach().
Speichere in einer Liste mit drei .item-Elementen sowohl list.getElementsByClassName("item") als auch list.querySelectorAll(".item"). Hänge ein viertes passendes Element an. Die dynamische Sammlung hat nun die Länge 4; die Momentaufnahme hat weiterhin die Länge 3.
Vermeide die Falle einer schrumpfenden dynamischen Sammlung
Angenommen, vier Elemente gehören zu einer dynamischen Sammlung namens live:
for (let i = 0; i < live.length; i++) {
live[i].classList.remove("item");
}
Das Entfernen der ersten Klasse entfernt dieses Element aus der Sammlung. Das nächste Element rückt auf Index 0, aber die Schleife geht zu Index 1 weiter und überspringt es. Nur zwei der vier verlieren die Klasse. Durchlaufe Array.from(live) oder eine Momentaufnahme von querySelectorAll(), wenn sich die Zugehörigkeit ändert.
Prüfe Leerzeichen in Selektoren
.task.done bedeutet ein Element mit beiden Klassen. .task .done bedeutet ein .done-Nachfahrenelement innerhalb eines .task. Zähle bei <li class="task done"> erledigte Einträge mit document.querySelectorAll(".task.done").length. Ein Komma kombiniert Selektoren: "h2, h3" gibt Treffer in Dokumentreihenfolge zurück, nicht erst alle Überschriften eines Typs und dann die des anderen.
Wichtige Erkenntnisse
- Durchlaufe die Mitglieder einer Sammlung, um ihre Inhalte oder Klassen zu ändern.
- querySelectorAll() gibt eine statische NodeList zurück; ein leeres Ergebnis hat die Länge 0.
- Wandle Sammlungen mit Array.from() oder Spread um, bevor du Methoden verwendest, die nur Arrays haben.
- Bei dynamischen Sammlungen ändert sich die Zugehörigkeit, wenn sich passende Elemente ändern.
- Erstelle eine Momentaufnahme vor einer Schleife, die Mitglieder einer dynamischen Sammlung entfernt.
- Ein Leerzeichen in einem Selektor ändert die gesuchte Beziehung.
3Aktualisiere Inhalte und Elementdaten
Ein Element enthält verschiedene Arten von Informationen: sichtbaren Text, HTML-Struktur, Attribute und JavaScript-Eigenschaften. Wenn du die richtige Art wählst, kannst du eine Beschriftung aktualisieren, einen Link ändern, ein Feld lesen oder einen angezeigten Eintrag mit seinen Daten verbinden. Derselbe Text kann als gewöhnliche Zeichen behandelt oder als HTML geparst werden, mit sehr unterschiedlichen Ergebnissen. Achte genau auf diese Unterschiede, damit Aktualisierungen den gewünschten Inhalt zeigen und externer Text sicher bleibt.
3.1 Wähle Text oder HTML für Inhaltsänderungen
Text und HTML sind unterschiedliche Eingaben. Einfacher Text soll als Zeichen erscheinen; HTML beschreibt Elemente, die der Browser aufbauen muss. Die Wahl zwischen beiden beeinflusst sowohl die Seitenstruktur als auch die Frage, ob externer Text unerwünschten Code ausführen kann.
Lies und ersetze Text
Bei <p id="msg">Total: <strong>3</strong> items</p> ist msg.textContent gleich „Total: 3 items“. Die Eigenschaft fügt Text aus den Nachfahrenelementen zusammen, ohne deren Tags aufzunehmen, und schließt durch CSS ausgeblendeten Text ein.
Das Setzen von textContent ersetzt alle Kindknoten durch einen Textknoten. Nach msg.textContent = "Cart is empty" existiert das <strong>-Kindelement nicht mehr innerhalb des Absatzes. Das Setzen von msg.textContent = "<b>Hi</b>" zeigt die tatsächlichen Zeichen „Hi“ an; es erstellt kein Element für Fettschrift.
Textwerte sind Zeichenketten. Enthält ein Zähler „4“, ergibt count.textContent + 1 den Wert „41“. Wandle vor dem Addieren um:
count.textContent = Number(count.textContent) + 1;
Die Addition ergibt die Zahl 5 und die Zuweisung zeigt ihre Textform „5“ an.
Lies Text entsprechend dem Layout
Bei einem gerenderten Element folgt innerText dem angezeigten Text und Layout. Die Eigenschaft lässt mit display: none ausgeblendete Nachfahrenelemente aus und enthält Zeilenumbrüche entsprechend dem Layout. Das Lesen kann eine Layoutberechnung erfordern. Verwende textContent für gewöhnliche Textarbeit und wähle innerText, wenn du den gerenderten Text benötigst. Ist das Element selbst losgelöst oder wird es nicht gerendert, greift innerText auf seinen Textinhalt zurück.
Parse HTML bewusst
innerHTML liest das Markup innerhalb eines Elements. Beim Setzen wird die Zeichenkette geparst und die Kindknoten werden ersetzt:
msg.innerHTML = "Total: <strong>5</strong> items";
Dadurch entsteht ein neues <strong>-Element. Die Methode eignet sich für Markup, das du geschrieben hast und kontrollierst. Verwende für Text von Nutzern oder aus externen Daten textContent und baue die Struktur mit createElement() auf.
Das Einfügen nicht vertrauenswürdigen HTMLs kann Cross-Site-Scripting (XSS) ermöglichen: Vom Angreifer kontrollierter Code wird im Browser des Besuchers ausgeführt. Ein eingeschleustes Bild kann ein onerror-Attribut tragen, das Code ausführt, wenn das Laden des Bildes fehlschlägt. Von innerHTML eingefügte Script-Tags werden nicht ausgeführt, aber das macht anderes eingeschleustes HTML nicht sicher. Das alleinige Blockieren von Script-Tags lässt diesen Angriffsweg offen.
Erhalte vorhandene Kindknoten beim Hinzufügen von Inhalt
list.innerHTML += "<li>New</li>" liest das vorhandene Markup, hängt eine Zeichenkette an und parst und ersetzt dann sämtliche Kindknoten. Ihre Objektidentität bleibt nicht erhalten. Eine Variable, die einen alten Kindknoten enthält, enthält weiterhin dieses losgelöste Objekt, und eingegebene Werte in ersetzten Eingabefeldern können verloren gehen. Verwende append() mit neuen Knoten oder insertAdjacentHTML("beforeend", markup) für vertrauenswürdiges Markup, um Inhalte hinzuzufügen, ohne vorhandene Kindknoten neu zu erstellen.
outerHTML enthält neben dem Inhalt auch das Tag des Elements selbst. Beim Setzen wird das Element selbst ersetzt. Eine gespeicherte Referenz verweist nach diesem Ersetzen weiterhin auf das alte, losgelöste Element; sie wechselt nicht automatisch zum neuen.
Wichtige Erkenntnisse
- textContent verarbeitet einfachen Text und ersetzt bei einer Zuweisung die Kindknoten des Elements.
- Wandle Text vor dem Rechnen in eine Zahl um.
- innerText folgt dem gerenderten Layout; innerHTML parst Markup.
- Halte nicht vertrauenswürdigen Text aus Zuweisungen heraus, die HTML parsen.
- innerHTML += erstellt vorhandene Kindknoten neu; append() erhält sie.
- Eine Zuweisung an outerHTML ersetzt das Element und lässt alte Referenzen auf das losgelöste Element verweisen.
3.2 Unterscheide Attribute von Objekteigenschaften
Ein Attribut ist ein Name mit einem Wert in HTML. Eine Eigenschaft gehört zum JavaScript-Objekt, das ein Element repräsentiert. Viele Standardattribute haben entsprechende Eigenschaften, aber diese können Werte verarbeiten oder eine andere Art von Zustand melden.
Arbeite über den Namen mit einem Attribut
Bei <img src="logo.png" alt="Company logo"> initialisiert der Browser Eigenschaften wie img.src und img.alt. Du kannst auch Methoden verwenden, die den Attributnamen als Zeichenkette entgegennehmen:
getAttribute(name)gibt eine Zeichenkette odernullzurück, wenn das Attribut fehlt.setAttribute(name, value)fügt ein Attribut hinzu oder ändert es und speichert seinen Wert als Text.hasAttribute(name)meldet, ob das Attribut vorhanden ist.removeAttribute(name)entfernt es.
Zum Beispiel ändert link.setAttribute("href", "https://example.com/help") das Ziel eines Links. Fehlt das Attribut target, gibt link.getAttribute("target") den Wert null zurück, keine leere Zeichenkette.
Lies den Wert, den du tatsächlich benötigst
Auf einer Seite unter https://example.com/shop/ hat der Link <a href="/about"> den Attributwert „/about“. Seine Eigenschaft href ist die aufgelöste URL, "https://example.com/about". Lies das Attribut, wenn du den Wert genau wie geschrieben benötigst, und die Eigenschaft, wenn du die aufgelöste URL benötigst.
Eigenschaften können andere Typen als Zeichenketten haben. button.disabled ist ein boolescher Wert; input.maxLength ist eine Zahl. Attributmethoden geben weiterhin Zeichenketten oder null zurück. Eigenschaftsnamen sind außerdem JavaScript-Namen, bei denen zwischen Groß- und Kleinschreibung unterschieden wird: el.id funktioniert, während el.ID eine andere Eigenschaft ist und normalerweise undefined ergibt.
Die meisten Namen sind vertraut, aber es gibt Ausnahmen. Das HTML-Attribut class ist über className und classList zugänglich. Das Attribut for eines Labels entspricht seiner Eigenschaft htmlFor:
label.htmlFor = "email";
Das verbindet das Label mit dem Element, dessen ID „email“ ist.
Behandle boolesche Attribute nach ihrem Vorhandensein
Zu den booleschen Attributen gehören disabled, checked, required und readonly. Ist das Attribut vorhanden, ist es wahr, selbst wenn sein Text „false“ ist. Dieser Code deaktiviert eine Schaltfläche:
button.setAttribute("disabled", "false");
Um sie zu aktivieren, setze button.disabled = false oder rufe button.removeAttribute("disabled") auf. button.toggleAttribute("disabled", isBusy) fügt das Attribut hinzu, wenn isBusy wahr ist, und entfernt es, wenn der Wert falsch ist.
Beschreibe Bedienelemente barrierefrei
ARIA-Attribute liefern Informationen für assistive Technologien. Attributmethoden eignen sich, um sie zu setzen, etwa button.setAttribute("aria-label", "Close dialog"), um eine Schaltfläche zu benennen, die nur ein Symbol zeigt. Ihre Werte sind Zeichenketten; zum Beispiel ist der Wert für einen aufgeklappten Zustand „true“ oder „false“.
Verwende Eigenschaften für häufige Vorgänge wie img.src = "photo.jpg" oder input.disabled = true. Verwende Attributmethoden, wenn der Name in einer Variablen steht, der genaue geschriebene Wert wichtig ist oder das Attribut keine entsprechende Eigenschaft hat, die du verwendest.
Verfolge eine Eigenschaftsänderung bis zum HTML zurück
const field = document.createElement("input");
field.disabled = true;
console.log(field.hasAttribute("disabled"));
console.log(typeof field.disabled);
console.log(typeof field.getAttribute("disabled"));
field.removeAttribute("disabled");
console.log(field.disabled);
Die Ausgaben sind true, „boolean“, „string“ und false. Das Setzen der Eigenschaft fügt das boolesche Attribut hinzu. Das Lesen dieses Attributs gibt weiterhin Text zurück, obwohl die Eigenschaft boolesch ist. Das Entfernen setzt die Eigenschaft wieder auf falsch. Methode und Eigenschaft zeigen dasselbe Vorhandensein über unterschiedliche Werttypen an.
Wichtige Erkenntnisse
- Attribute speichern HTML-Werte; Eigenschaften können typisierte oder verarbeitete Werte bereitstellen.
- getAttribute() gibt eine Zeichenkette oder bei fehlendem Attribut null zurück.
- Boolesche Attribute sind durch ihr Vorhandensein wahr, auch bei disabled="false".
- Verwende Eigenschaftsnamen wie className und htmlFor, wenn sich die HTML-Namen unterscheiden.
- ARIA-Werte sind Zeichenketten, die das Element für assistive Technologien beschreiben.
3.3 Verbinde Elemente mit Daten und lies Felder aus
Ein Element kann eine ID für die von ihm angezeigten Daten tragen, ohne diese ID auf dem Bildschirm anzuzeigen. Auch Formularsteuerelemente tragen Werte, aber ihr aktueller Inhalt wird über Eigenschaften gelesen. Beide Arten von Werten müssen vor Vergleichen oder Rechnungen oft umgewandelt werden.
Speichere benutzerdefinierte Daten mit Datenattributen
HTML-Namen, die mit data- beginnen, speichern Informationen für Skripte:
<li data-task-id="17" data-priority="high">Prepare slides</li>
Das Objekt dataset stellt diese Attribute bereit. Entferne das Präfix data- und ersetze jeden Bindestrich vor einem Kleinbuchstaben durch diesen Großbuchstaben: Aus data-task-id wird dataset.taskId. Aus data-priority wird dataset.priority.
li.dataset.dueDate = "2026-11-05";
delete li.dataset.priority;
Die Zuweisung erstellt data-due-date="2026-11-05". Das delete entfernt data-priority. Datenattribute lassen sich auch mit CSS-Attributselektoren wie '[data-priority="high"]' auswählen.
Ein frei erfundenes Attribut wie taskid="17" ist ungültiges HTML und erstellt keine Eigenschaft li.taskid. getAttribute("taskid") kann es weiterhin lesen, aber data-task-id ist die korrekte Form für benutzerdefinierte Daten.
Wandle Zeichenkettenwerte bewusst um
li.dataset.taskId ist „17“, eine Zeichenkette. li.dataset.taskId === 17 ist falsch, weil sich die Typen unterscheiden. Sind die IDs in den Daten Zahlen, verwende Number(li.dataset.taskId) === 17. Ein fehlendes Datenattribut ergibt undefined. Die Zuweisung li.dataset.count = 3 speichert den Text „3“.
Das schafft eine nützliche Verbindung von einem angezeigten Eintrag zurück zu seinem Objekt:
const id = Number(li.dataset.taskId);
const task = tasks.find(task => task.id === id);
Der Vergleich verwendet nun zwei Zahlen. Hat kein Objekt diese ID, gibt find() den Wert undefined zurück; prüfe das, bevor du seine Eigenschaften liest.
Lies den aktuellen Wert eines Felds
Ein <input> enthält den eingegebenen Wert nicht als Textinhalt. Lies input.value, eine Zeichenkette, oder weise der Eigenschaft einen Wert zu, um das Feld zu ändern. input.value = "" leert es.
Bei <input id="qty" value="1"> ist qty.value gleich „3“, nachdem der Nutzer 3 eingegeben hat, aber qty.getAttribute("value") ist weiterhin „1“. Das Attribut liefert den Anfangswert; die Eigenschaft liefert den aktuellen Wert. Ein Kontrollkästchen funktioniert ähnlich: Seine Eigenschaft checked meldet seinen aktuellen booleschen Zustand, während das Attribut den anfänglichen Auswahlzustand beschreibt.
Verwende für jedes Bedienelement den richtigen Wert
Selbst <input type="number"> hat einen value als Zeichenkette. Ist die Menge „3“ und wiegt jeder Artikel 0,25 kg, ergibt Number(qty.value) * 0.25 den Wert 0,75 kg. Aber qty.value + 1 ergibt „31“, weil + eine Zeichenkette und eine Zahl verkettet. Ein <select> gibt den Wert der ausgewählten Option über select.value zurück. Lies bei einem Kontrollkästchen checkbox.checked, nicht checkbox.value, wenn du wissen musst, ob es ausgewählt ist.
Wichtige Erkenntnisse
- dataset bildet data-task-id auf taskId ab und speichert Zeichenkettenwerte.
- Verwende delete auf einer dataset-Eigenschaft, um ihr Datenattribut zu entfernen.
- Wandle Daten-IDs vor einem strikten Vergleich mit numerischen IDs um.
- Lies den aktuellen Inhalt von input und select über value.
- Lies den aktuellen Auswahlzustand eines Kontrollkästchens über checked.
- Die anfänglichen Attribute value und checked können von den aktuellen Eigenschaften der Bedienelemente abweichen.
4Steuere Aussehen und Sichtbarkeit
JavaScript kann das Aussehen einer Seite ändern, indem es Klassen umschaltet, einen berechneten Inline-Wert setzt oder einen Abschnitt ausblendet. Diese Möglichkeiten wirken mit dem CSS zusammen, das bereits auf der Seite steht. Lerne, welcher Zustand in eine Klasse gehört, welche Werte Einheiten benötigen und wie du den vom Browser angewandten Stil liest. Das Ein- und Ausblenden wirkt sich auch auf das Layout und assistive Technologien aus. Halte daher sichtbare Bereiche und ihre Attribute für Barrierefreiheit aufeinander abgestimmt.
4.1 Schalte Klassen um, ohne die Grundgestaltung zu verlieren
Belasse feste visuelle Regeln im CSS und lass JavaScript dann die Klassen ändern, die diese Regeln auswählen. Eine Klasse kann einen Zustand wie „erledigt“, „aktiv“ oder „Fehler“ ausdrücken, ohne die zugehörigen Farben und Dekorationen im Code zu wiederholen.
Füge Klassentoken hinzu und entferne sie
Angenommen, das Stylesheet enthält:
.done { text-decoration: line-through; color: #888; }
item.classList.add("done") wendet das Erscheinungsbild für erledigte Einträge an. item.classList.remove("done") entfernt diesen Zustand und lässt andere Klassen unverändert. Beide Methoden akzeptieren mehrere Namen; das Hinzufügen einer vorhandenen oder das Entfernen einer fehlenden Klasse ist unproblematisch.
contains("done") gibt einen booleschen Wert zurück. replace("wide", "narrow") ersetzt eine vorhandene Klasse durch eine andere. toggle("active") fügt eine fehlende Klasse hinzu oder entfernt eine vorhandene und gibt zurück, ob die Klasse danach vorhanden ist.
Verfolge eine Klassenänderung
Beginne mit <div class="card">:
card.classList.add("active", "wide");
const active = card.classList.toggle("active");
const replaced = card.classList.replace("wide", "narrow");
Nach der ersten Zeile lauten die Klassen „card active wide“. Das Umschalten entfernt „active“, sodass active gleich false ist und die Klassen zu „card wide“ werden. Das Ersetzen von „wide“ hinterlässt „card narrow“ und gibt true zurück. Ein späteres card.classList.contains("active") ist false.
Setze eine Klasse anhand einer Bedingung
Wenn die Daten den gewünschten Zustand vorgeben, übergib ein zweites Argument:
row.classList.toggle("overdue", daysLeft < 0);
Ein negativer Wert für daysLeft sorgt dafür, dass die Klasse vorhanden ist; andernfalls fehlt sie. Wiederholst du den Aufruf, bleibt dieser Zustand erhalten. Ein einfaches toggle("overdue") würde ihn bei jedem Aufruf umkehren.
Erhalte den Rest des Klassenattributs
className ist die vollständige Klassenzeichenkette. card.className = "active" ersetzt alle vorhandenen Klassen, einschließlich „card“. Verwende diese Zuweisung, wenn du alle Klassen ersetzen möchtest; verwende classList für Änderungen einzelner Zustände.
Übergib reine Klassennamen ohne Satzzeichen aus CSS-Selektoren. classList.add(".active") fügt ein Token hinzu, das tatsächlich einen Punkt enthält; es ist nicht die Klasse, auf die .active passt. Ein einzelnes Argument darf keine Leerzeichen enthalten: classList.add("big red") löst einen InvalidCharacterError aus. Schreibe classList.add("big", "red") für zwei Klassen.
Prüfe das CSS, wenn sich das Aussehen nicht ändert
Hat eine Klasse keine sichtbare Wirkung, untersuche ihr Token und ihre Regel in den DevTools. Prüfe, ob eine Regel fehlt oder falsch geschrieben ist und ob im Bereich „Styles“ übersteuerte Deklarationen durchgestrichen sind.
Wichtige Erkenntnisse
- classList ändert einzelne Klassentoken und erhält andere Klassen.
- toggle(name) gibt zurück, ob die Klasse danach vorhanden ist.
- toggle(name, condition) setzt eine Klasse anhand von Daten, ohne sie bei jeder Ausführung umzukehren.
- Eine Zuweisung an className ersetzt die gesamte Klassenzeichenkette.
- Übergib reine Namen getrennt, ohne Selektorpunkte oder Leerzeichen innerhalb eines Tokens.
4.2 Setze berechnete Stile und lies angewandte Stile aus
Verwende Klassen für feste Designs und Inline-Stile für berechnete Werte. Das Objekt style liest und schreibt Inline-Deklarationen, nicht alle Regeln, die ein Element beeinflussen.
Schreibe CSS-Werte über style
CSS-Namen mit Bindestrichen werden zu JavaScript-Eigenschaften in camelCase. Aus background-color wird backgroundColor, aus font-size wird fontSize und aus z-index wird zIndex:
box.style.backgroundColor = "gold";
box.style.width = "250px";
Stilwerte sind Zeichenketten. Gib eine Einheit an, wenn die Eigenschaft sie benötigt. Auf einer Seite im Standardmodus wird die Zuweisung box.style.width = 250 ignoriert, weil eine Breite ungleich null eine CSS-Einheit benötigt. Die Zeichenkette „0“ ist für eine Breite von null gültig.
style.setProperty() erwartet stattdessen die CSS-Schreibweise:
box.style.setProperty("background-color", "gold");
document.documentElement.style.setProperty("--accent", "#0a7d5a");
Die benutzerdefinierte Eigenschaft am Wurzelelement liefert den Wert für Regeln, die auf var(--accent) verweisen.
Wandle ein Rechenergebnis in einen CSS-Wert um
Ein Fortschrittsbalken zeigt 3 erledigte Aufgaben von 8:
const percent = (3 / 8) * 100;
bar.style.width = `${percent}%`;
Der Anteil 0,375 wird zu 37,5 Prozent. Das Template-Literal liefert „37.5%“ einschließlich der benötigten Einheit.
Entferne eine vorübergehende Überschreibung
Setze box.style.backgroundColor = "" oder rufe box.style.removeProperty("background-color") auf, um diese Inline-Deklaration zu entfernen. Der Browser wendet dann die verbleibenden Stylesheet-Regeln an. Verwende bei removeProperty() den CSS-Namen mit Bindestrichen.
Sei vorsichtig mit style.cssText. Die Zuweisung box.style.cssText = "color: red" ersetzt den gesamten Inline-Stil, sodass eine vorhandene Inline-Breite verloren geht. Das Ändern einer einzelnen Stileigenschaft lässt die anderen Inline-Deklarationen unverändert.
Lies, was der Browser anwendet
Färbt ein Stylesheet einen Absatz rot, hat dieser aber keine Inline-Farbe, ist p.style.color eine leere Zeichenkette. Verwende getComputedStyle(p).color für den angewandten Wert, häufig „rgb(255, 0, 0)“. Berechnete Werte sind schreibgeschützt; ändere die Klasse oder Inline-Deklaration, um das Aussehen zu ändern.
Inline-Deklarationen übersteuern gewöhnliche Stylesheet-Regeln, aber anwendbare !important-Deklarationen können Vorrang haben. Wenn eine Klassenänderung wirkungslos erscheint, prüfe, ob eine Inline-Überschreibung übrig geblieben ist.
Wichtige Erkenntnisse
- style liest und schreibt Inline-Deklarationen; camelCase entspricht CSS-Namen mit Bindestrichen.
- Gib in CSS-Wertzeichenketten Einheiten an, wenn sie benötigt werden.
- setProperty() und removeProperty() erwarten CSS-Namen mit Bindestrichen.
- Entferne eine Inline-Deklaration, damit Stylesheet-Regeln wieder gelten.
- getComputedStyle() meldet angewandte Werte, einschließlich der Stile aus CSS-Regeln.
4.3 Blende Inhalte aus und halte ihren Zustand eindeutig
Wenn du einen Bereich ausblendest, bleibt er im DOM und kann mit seinem vorhandenen Inhalt und seinen Feldwerten wieder angezeigt werden. Beim Entfernen verlässt er den Baum. Wähle das Ausblenden für einen Bereich, der wieder erscheinen soll, und das Entfernen für einen Eintrag, dessen Daten nicht mehr existieren.
Verwende die Eigenschaft hidden
panel.hidden = true setzt den gewöhnlichen ausgeblendeten Zustand. Der Standardstil des Browsers blendet den Bereich aus, ohne Platz im Layout zu lassen. panel.hidden = false entfernt diesen Zustand und zeigt ihn wieder an.
Ein Stylesheet kann diesen Standard übersteuern. Zum Beispiel kann .panel { display: flex; } einen ausgeblendeten Bereich sichtbar machen. Wenn der ausgeblendete Zustand immer Vorrang haben soll, füge Folgendes ein:
[hidden] { display: none !important; }
Alternativ kannst du die Sichtbarkeit mit einer CSS-Klasse steuern. Bei .is-hidden { display: none; } fügt menu.classList.toggle("is-hidden", !isOpen) die ausblendende Klasse hinzu, wenn das Menü geschlossen ist. Prüfe das Stylesheet, wenn die Klasse vorhanden ist, aber eine andere display-Deklaration Vorrang hat.
Vergleiche drei Arten des Ausblendens
display: none entfernt den Platz des Elements im Layout und verbirgt es vor Screenreadern. visibility: hidden macht es unsichtbar, erhält aber seinen Platz und verbirgt es ebenfalls vor Screenreadern. opacity: 0 macht es transparent, erhält aber seinen Platz; es kann weiterhin angeklickt werden und bleibt für Screenreader zugänglich. Transparenz allein ist daher eine schlechte Möglichkeit, einen Bereich zu schließen, der nicht mehr zugänglich sein soll.
Diese Auswirkungen betreffen Sichtbarkeit und Layout, nicht das Löschen. Ein ausgeblendetes Eingabefeld kann seinen eingegebenen Wert weiterhin behalten, weil dasselbe Eingabeobjekt im Baum bleibt.
Halte die Beschreibung des Bedienelements aktuell
Eine Schaltfläche für einen aufklappbaren Bereich sollte angeben, ob dieser aufgeklappt ist. Setze aria-expanded auf die Zeichenkette „true“, wenn er geöffnet ist, und auf „false“, wenn er geschlossen ist. Leite diesen Wert und die Sichtbarkeit des Bereichs aus demselben Zustand ab.
Für einen Antwortbereich, der als <div id="answer-1" hidden> beginnt, mit Referenzen namens answer und button, führe Folgendes aus:
const willOpen = answer.hidden;
answer.hidden = !willOpen;
button.setAttribute("aria-expanded", String(willOpen));
Anfangs ist answer.hidden gleich true, also ist willOpen wahr. Die Zuweisung setzt hidden auf falsch und zeigt den Bereich an. Das Attribut der Schaltfläche wird zu „true“. Führst du dieselben Anweisungen erneut aus, ist hidden zu Beginn falsch, der Bereich wird ausgeblendet und „false“ in das Attribut geschrieben.
Untersuche eine Abweichung
Wenn die Schaltfläche „aufgeklappt“ meldet, während der Bereich ausgeblendet ist, wurden die beiden Werte nicht gemeinsam aktualisiert. Ist hidden wahr, der Bereich aber weiterhin sichtbar, untersuche sein berechnetes display und die dafür verantwortliche CSS-Regel. Das erste Problem ist ein inkonsistenter Anwendungszustand; beim zweiten übersteuert ein Stil den ausgeblendeten Zustand. Wenn du sowohl die DOM-Eigenschaften als auch das angewandte CSS liest, kannst du sie unterscheiden.
Wichtige Erkenntnisse
- hidden behält Inhalte im DOM und blendet sie mit dem Standardstil aus.
- Eine explizite display-Regel kann hidden übersteuern; prüfe die beabsichtigte Regel oder setze sie durch.
- display: none entfernt den Platz; visibility: hidden erhält ihn.
- opacity: 0 erhält die Interaktion und die Zugänglichkeit für Screenreader.
- Aktualisiere aria-expanded anhand desselben geöffneten Zustands wie den Bereich.
5Erstelle und ändere Seitenstrukturen
Die Struktur einer Seite kann sich ändern, während sie geöffnet ist. Erstelle ein Element im Speicher, fülle es und füge es an der richtigen Stelle im Baum ein. Dieselben Einfügemethoden können einen vorhandenen Knoten verschieben, sodass das zweimalige Hinzufügen einer Referenz keine zwei Kopien erstellt. Entfernen, Ersetzen und Klonen verändern den Baum und die Referenzen deines Skripts auf unterschiedliche Weise. Wenn du diese Referenzen verfolgst, verstehst du, warum eine alte Variable manchmal auf losgelöste Inhalte verweist.
5.1 Erstelle einen Knoten, fülle ihn und füge ihn ein
Ein neues Element erscheint nicht allein dadurch, dass du es erstellt hast. Erstelle zuerst das Objekt, gib ihm dann Inhalt und Attribute und füge es schließlich in das Dokument ein. Vor dem Einfügen kannst du eine vollständig verschachtelte Struktur im Speicher zusammenstellen.
Erstelle einen vollständigen Eintrag
const li = document.createElement("li");
li.textContent = "Water the plants";
li.className = "task";
li.dataset.id = "4";
document.querySelector("#tasks").append(li);
createElement("li") erstellt ein leeres Element. Die nächsten Zeilen füllen es; die letzte fügt es als letzten Kindknoten der vorhandenen Aufgabenliste ein. Es entsteht <li class="task" data-id="4">Water the plants</li>. Der Aufruf benötigt einen Tag-Namen, kein Markup: createElement("<li>") löst einen InvalidCharacterError aus. Setze Klassen und Attribute nach dem Erstellen.
Erstelle für verschachtelten Inhalt ein span-Element für den Titel und eine Schaltfläche getrennt, setze ihren Text und rufe li.append(title, button) auf. Füge dann den zusammengesetzten Eintrag in die Liste ein. document.createTextNode("…") erstellt Text direkt; auch die Übergabe einer Zeichenkette an append() fügt einen Textknoten ein.
Wähle eine Einfügeposition
parent.append(...)fügt nach den vorhandenen Kindknoten hinzu.parent.prepend(...)fügt vor den vorhandenen Kindknoten hinzu.element.before(...)fügt vorherige Geschwisterknoten hinzu.element.after(...)fügt nachfolgende Geschwisterknoten hinzu.
Jede Methode akzeptiert mehrere Knoten und Zeichenketten. Zeichenketten werden als Text behandelt, sodass list.append("<li>New</li>") keinen Eintrag erstellt. Die spitzen Klammern erscheinen als Zeichen innerhalb der Liste.
Ältere Methoden kommen weiterhin im Code vor. appendChild(node) akzeptiert einen Knoten und gibt ihn zurück; die Methode akzeptiert keine Zeichenkette. append() gibt undefined zurück. parent.insertBefore(newNode, referenceNode) fügt einen Knoten vor einem vorhandenen Kindknoten ein; mit null als Referenz wird am Ende hinzugefügt.
Verstehe Verschieben und Kopieren
Ein Knoten kann im Baum nur einen Platz einnehmen. Das Einfügen eines vorhandenen Knotens verschiebt ihn. Bei einer Liste in der Reihenfolge a, b, c verschiebt list.prepend(list.lastElementChild) c an den Anfang, sodass c, a, b entsteht. Am Ende bleibt kein zweites c zurück.
Das erklärt auch einen häufigen Schleifenfehler: Wenn du ein <li> außerhalb einer Schleife erstellst und wiederholt anhängst, bleibt ein Eintrag übrig. Jeder Durchlauf ändert und verschiebt dasselbe Objekt. Erstelle bei jedem Durchlauf ein neues Element, wenn die Seite mehrere Einträge benötigt, oder erstelle separate Klone.
Füge vertrauenswürdiges Markup neben vorhandenem Inhalt ein
insertAdjacentHTML(position, markup) parst HTML, ohne vorhandene Kindknoten zu ersetzen. Die vier Positionsnamen sind "beforebegin" und "afterend" für Geschwisterknoten außerhalb des Elements sowie "afterbegin" und "beforeend" für Kindknoten innerhalb des Elements. list.insertAdjacentHTML("beforeend", "<li>New</li>") hängt einen geparsten Eintrag an. Verwende dies nur für vertrauenswürdiges Markup; externer Text gehört in textContent. insertAdjacentElement() und insertAdjacentText() verwenden dieselben Positionsnamen für ein Element beziehungsweise einfachen Text.
Wichtige Erkenntnisse
- Erstellen, Füllen und Einfügen sind getrennte Schritte.
- append/prepend fügen Kindknoten hinzu; before/after fügen Geschwisterknoten hinzu.
- Die Übergabe einer Zeichenkette an append() fügt Text ein, ohne HTML zu parsen.
- Das Einfügen eines vorhandenen Knotens verschiebt ihn, statt ihn zu kopieren.
- Erstelle bei jedem Schleifendurchlauf einen neuen Eintrag, wenn du mehrere Objekte benötigst.
- appendChild() akzeptiert einen Knoten und gibt ihn zurück; append() akzeptiert mehrere Eingaben und gibt undefined zurück.
- insertAdjacentHTML() erhält vorhandene Kindknoten, parst seine Eingabe aber weiterhin als HTML.
5.2 Entferne, ersetze und klone die richtigen Objekte
Das Entfernen eines Elements ändert den Baum, löscht aber nicht jede Referenz auf dieses Objekt. Beim Ersetzen gibt es einen ähnlichen Unterschied: Das neue Objekt nimmt seinen Platz ein, während gespeicherte Variablen weiterhin auf das alte verweisen können.
Entferne ein Element oder mehrere Treffer
element.remove() löst dieses Element aus dem Baum. parent.removeChild(child) ist die ältere Form über den Elternknoten und gibt den entfernten Knoten zurück. Enthält eine Variable den Knoten weiterhin, kann das Skript ihn später lesen oder wieder einfügen.
Um erledigte Aufgaben zu entfernen, wähle eine statische Sammlung aus und durchlaufe sie:
document.querySelectorAll(".task.done")
.forEach(task => task.remove());
Bei fünf Aufgaben, von denen zwei als erledigt markiert sind, bleiben drei übrig. Das Entfernen eines Elements ändert nicht, welche Referenzen die statische NodeList enthält, sodass die Schleife beide ausgewählten Aufgaben besucht.
Zähle nicht vorwärts durch eine schrumpfende dynamische Liste
list.children ist dynamisch. Bei sechs Kindknoten entfernt eine vorwärts laufende Schleife, die items[i] entfernt, nur drei. Nach dem ersten Entfernen rückt das zweite Element auf Index 0, aber i geht zu 1 weiter. Der nächste ursprüngliche Kindknoten wird übersprungen und dieselbe Verschiebung wiederholt sich.
Erstelle eine Momentaufnahme, bevor du alle aktuellen Kindknoten entfernst:
Array.from(list.children).forEach(item => item.remove());
Um einen Container lediglich zu leeren, ist list.replaceChildren() übersichtlicher. Auch das Setzen von list.textContent = "" oder list.innerHTML = "" leert ihn. Eine leere Zeichenkette parst keinen externen Inhalt.
Ersetze einen einzelnen Knoten oder alle Kindknoten
old.replaceWith(newElement) setzt einen neuen Knoten an die Stelle des alten. Bei <p id="status">Loading…</p> ersetzt document.querySelector("#status").replaceWith(list) die Meldung durch die Liste. parent.replaceChildren(a, b, c) ersetzt alle Kindknoten des Elternknotens in einem Vorgang und erhält dabei den Elternknoten selbst.
Dieser Unterschied ist für gespeicherte Referenzen wichtig. Eine Variable, die den Elternknoten enthält, bleibt nach replaceChildren() erhalten, aber Referenzen auf die entfernten Kindknoten verweisen nun auf losgelöste Objekte. Das Ersetzen eines Containers mit replaceWith() löst auch diesen Container aus dem Baum.
Kopiere das Element mit oder ohne Nachfahrenknoten
element.cloneNode(true) erstellt eine tiefe Kopie, einschließlich Nachfahrenknoten und Attributen. cloneNode() oder cloneNode(false) kopiert das Element und seine Attribute ohne seine Kindknoten. Ein geklonter Listeneintrag ohne Nachfahrenknoten enthält keinen Text des ursprünglichen Eintrags.
Ein Klon ist anfangs losgelöst und muss eingefügt werden. Er übernimmt auch die ID des Originals. Gib ihm eine neue ID oder entferne das Attribut, bevor du ihn auf derselben Seite platzierst, damit die Auswahl über IDs zuverlässig bleibt.
Behandle optionale Elemente
Wenn eine Suche fehlschlagen kann, rufe nicht sofort eine Methode auf ihrem Ergebnis auf. document.querySelector("#promo").remove() löst einen Fehler aus, wenn kein Werbebereich vorhanden ist. document.querySelector("#promo")?.remove() tut in diesem Fall sicher nichts. Bei einem benötigten Container ist ein fehlendes Ergebnis ein nützliches Signal, Selektor und Ausführungszeitpunkt des Skripts zu prüfen, bevor du eine strukturelle Änderung versuchst.
Wichtige Erkenntnisse
- remove() löst einen Knoten aus dem Baum; über eine gespeicherte Referenz kannst du ihn weiterhin verwenden oder erneut einfügen.
- Verwende eine statische Liste, wenn du mehrere ausgewählte Elemente entfernst.
- replaceChildren() erhält den Container und ersetzt oder entfernt seine Kindknoten.
- replaceWith() ersetzt den ausgewählten Knoten selbst.
- cloneNode(true) kopiert Nachfahrenknoten; ein flacher Klon lässt sie aus.
- Klonen kopiert IDs, ändere oder entferne daher eine kopierte ID vor dem Einfügen.
6Wandle Daten in eine Seite um
Arrays beschreiben, was eine Seite anzeigen soll; beim Rendern werden diese Beschreibungen in Elemente umgewandelt. Beginne mit einem Eintrag, erweitere das Muster auf Listen und Tabellen und organisiere dann wiederholtes Markup mit Fragmenten oder Templates. Eine Renderfunktion macht spätere Aktualisierungen bei Datenänderungen vorhersagbar. Unterscheide das ursprüngliche Array, die ausgewählte Ansicht und die angezeigten Elemente, damit Filterung, Sortierung, leere Ergebnisse und Zusammenfassungen konsistent bleiben.
6.1 Rendere Arrayeinträge als Listeneinträge und Tabellenzeilen
Rendern bedeutet, Daten in eine sichtbare DOM-Struktur umzuwandeln. Behalte das Array als Quelle und erstelle für jedes Objekt ein Element. Setze Datenwerte in textContent, damit sie Text bleiben, selbst wenn sie spitze Klammern enthalten.
Erstelle für jedes Objekt ein Element
Verwende diese Buchobjekte:
const books = [
{ id: 1, title: "Dune", pages: 412 },
{ id: 2, title: "Emma", pages: 474 },
{ id: 3, title: "Beloved", pages: 324 }
];
function createBookItem(book) {
const li = document.createElement("li");
li.dataset.id = String(book.id);
li.textContent = `${book.title} (${book.pages} pages)`;
return li;
}
const list = document.querySelector("#books");
list.append(...books.map(createBookItem));
map() ruft die Erstellungsfunktion einmal pro Buch auf und liefert drei getrennte Elemente. Die Spread-Syntax übergibt diese Elemente als separate Argumente an append(). Die Anzeige lautet „Dune (412 pages)“, „Emma (474 pages)“ und „Beloved (324 pages)“. Die Seitenzahlen ergeben zusammen 1.210.
Ohne Spread erhält list.append(books.map(createBookItem)) ein einzelnes Array. Die Methode wandelt dieses Array in Text mit Zeichenketten wie „[object HTMLLIElement]“ um, statt die Eintragselemente einzufügen.
Die gespeicherte ID verbindet das angezeigte Element mit den Daten. Lies Number(li.dataset.id), bevor du den Wert mit numerischen Buch-IDs vergleichst, und verwende dann books.find(book => book.id === id).
Behandle fehlende und leere Daten
Fehlt ein optionales Autorenfeld, zeigt eine direkte Interpolation „undefined“ an. Verwende book.author ?? "Unknown author" als Ersatzwert, wenn das Feld null oder undefined ist. Der Nullish-Coalescing-Operator lässt andere Werte, einschließlich 0 und einer leeren Zeichenkette, unverändert.
Ist das Array leer, zeige eine Meldung wie „Noch keine Bücher“ an. Ein leeres Ergebnis sollte dem Nutzer mitteilen, dass derzeit keine Einträge vorhanden sind. Ersetze beim erneuten Rendern die alte Anzeige, damit eine frühere Meldung oder frühere Einträge nicht neben dem neuen Ergebnis stehen bleiben.
Verstehe die Vorgehensweise mit HTML-Zeichenketten
Ein vertrauenswürdiges Array kann auf HTML-Zeichenketten abgebildet und vor der Zuweisung an innerHTML mit join("") zusammengefügt werden. Das Zusammenfügen entfernt die Kommas, die die Umwandlung des Arrays in eine Zeichenkette andernfalls einfügen würde. Bei dieser Vorgehensweise wird jeder interpolierte Wert als HTML geparst. Verwende das Erstellen von Elementen, wenn Werte aus externen Quellen stammen können.
Erstelle eine gültige Tabellenstruktur
Erstelle für Tabellendaten ein <tr> pro Objekt und ein <td> für jedes angezeigte Feld. Hänge die Zeilen an den <tbody> der Tabelle an. Für Messwerte aus Oslo bei 4,25 °C und Kairo bei 28,5 °C kann die Temperaturzelle reading.temp.toFixed(1) verwenden: Die Anzeige lautet „4.3“ und „28.5“. toFixed() gibt eine Zeichenkette mit den angeforderten Dezimalstellen zurück. toLocaleString() formatiert dagegen für das Gebietsschema des Nutzers, das ein Dezimalkomma verwenden kann. Formatiere erst bei der Anzeige, damit die numerischen Daten für Berechnungen verfügbar bleiben.
Erstelle beide Zellen vor dem Einfügen der Zeile
Für einen vorhandenen leeren Tabellenkörper namens tbody rendert dies die Messwerte:
const readings = [{ city: "Oslo", temp: 4.25 }, { city: "Cairo", temp: 28.5 }];
const rows = readings.map(reading => {
const row = document.createElement("tr");
const city = document.createElement("td");
const temperature = document.createElement("td");
city.textContent = reading.city;
temperature.textContent = reading.temp.toFixed(1) + " °C";
row.append(city, temperature);
return row;
});
tbody.replaceChildren(...rows);
Jeder Durchlauf erstellt eine neue Zeile und zwei neue Zellen. Wenn du beide Zellen vor dem Anhängen der Zeile füllst, bleibt die Reihenfolge der Felder eindeutig. Die Spread-Syntax übergibt die beiden Zeilenknoten aus rows getrennt; das abschließende Ersetzen entfernt auch frühere Zeilen.
Wichtige Erkenntnisse
- Erstelle für jedes Datenobjekt ein eigenes Element und fülle Werte mit textContent ein.
- Verwende Spread für ein Array aus Knoten, wenn du sie an append() übergibst.
- Verwende Datenattribute, um angezeigte Elemente mit Objekten zu verbinden.
- Stelle Meldungen für Leerzustände und Ersatzwerte für null oder undefined bereit.
- Setze Tabellenzeilen in tbody und Felder in Zellen.
- toFixed() gibt Anzeigetext zurück; behalte numerische Daten für Berechnungen.
6.2 Setze wiederholte Inhalte vor dem Einfügen zusammen
Wenn eine Liste viele Einträge enthält, erstelle den neuen Inhalt außerhalb der Seite und füge ihn gemeinsam ein. Ein DocumentFragment gruppiert Knoten, ohne ein umschließendes Element hinzuzufügen. Mit einem template-Element kannst du eine wiederholte Struktur in HTML schreiben und für jedes Objekt eine neue Kopie füllen.
Sammle Knoten in einem Fragment
const fragment = document.createDocumentFragment();
for (const book of books) {
fragment.append(createBookItem(book));
}
list.append(fragment);
Das Fragment beginnt außerhalb des Dokuments. Jeder neue Eintrag wird zu seinem Kindknoten. Das Anhängen des Fragments verschiebt seine Kindknoten in ihrer bisherigen Reihenfolge in die Liste; das Fragment selbst wird nicht als umschließendes Element eingefügt. Nachdem 100 Einträge in eine leere Liste übertragen wurden, hat die Liste 100 Kindknoten und das Fragment 0.
Dieses Muster bündelt das Einfügen und hält den Erstellungscode übersichtlich. Es verspricht keinen bestimmten Geschwindigkeitsgewinn. Ein Array erstellter Knoten funktioniert ebenfalls: list.append(...items) fügt sie hinzu, während list.replaceChildren(...items) den aktuellen Inhalt durch sie ersetzt.
Definiere wiederholtes Markup in einem Template
<template id="book-row">
<li class="book"><span class="title"></span>
(<span class="pages"></span> pages)</li>
</template>
Der Browser parst dieses Markup, ohne es anzuzeigen. Der Inhalt liegt in einem separaten DocumentFragment unter template.content. Eine Suche auf Dokumentebene durchsucht dieses Fragment nicht. Wähle das Template aus, klone seinen Inhalt und suche dann innerhalb des Klons:
const template = document.querySelector("#book-row");
const clone = template.content.cloneNode(true);
clone.querySelector(".title").textContent = book.title;
clone.querySelector(".pages").textContent = book.pages;
const item = clone.firstElementChild;
list.append(clone);
Titel und Seitenzahl werden vor dem Einfügen ausgefüllt. item speichert eine Referenz auf das neue <li>. Nach dem Anhängen ist clone leer, weil seine Kindknoten verschoben wurden, aber item verweist weiterhin auf das eingefügte Element.
Erhalte die wiederverwendbare Quelle
Hänge jedes Mal eine Kopie an. Der Aufruf list.append(template.content) verschiebt die Quellknoten aus dem Template. Eine spätere Suche innerhalb von template.content gibt dann null zurück und der nächste Versuch, den fehlenden Titel zu füllen, löst einen Fehler aus. Das Quell-Template sollte für spätere Bücher verfügbar bleiben.
Fülle für viele Kopien jedes geklonte Fragment, hänge diese Kopien an ein Sammelfragment an und füge dann die Sammlung ein. Ein Fragment kann die Kindknoten eines anderen Fragments ebenso aufnehmen wie eine Liste.
Wähle eine lesbare Erstellungsmethode
createElement() eignet sich für eine kleine Struktur oder eine, die sich je nach Eintrag stark unterscheidet. Ein Template eignet sich für größeres wiederholtes Markup, das sich als HTML leichter bearbeiten lässt. Füge in beiden Fällen externe Werte als Text ein. Eine HTML-Zeichenkette eignet sich für vertrauenswürdiges Markup, aber die Interpolation darin löst weiterhin das Parsen von HTML aus. Wähle die Erstellungsmethode anhand der Struktur, die du pflegen musst, und behalte dabei die Reihenfolge Erstellen oder Klonen, Füllen und Einfügen bei.
Sammle gefüllte Kopien für ein einmaliges Ersetzen
Mit dem obigen Buch-Template und einem vorhandenen books-Array:
const group = document.createDocumentFragment();
for (const book of books) {
const copy = template.content.cloneNode(true);
copy.querySelector(".title").textContent = book.title;
copy.querySelector(".pages").textContent = book.pages;
group.append(copy);
}
list.replaceChildren(group);
Jede gefüllte Kopie überträgt ihren Eintrag in group. Die letzte Zeile ersetzt den Listeninhalt durch diese Einträge und leert group. Das ursprüngliche Template bleibt währenddessen unverändert, sodass die Funktion den Aufbau für ein späteres Array wiederholen kann.
Wichtige Erkenntnisse
- Das Anhängen eines Fragments verschiebt seine Kindknoten und lässt das Fragment leer zurück.
- Ein Fragment gruppiert Knoten, ohne ein umschließendes Element auf der Seite zu erstellen.
- Template-Inhalte werden geparst, liegen aber außerhalb des angezeigten Dokumentbaums.
- Klone template.content für jeden Eintrag und fülle den Klon vor dem Einfügen.
- Speichere die Referenz auf den Eintrag, bevor das enthaltende Fragment geleert wird.
6.3 Halte gerenderte Ansichten mit den Daten aktuell
Verwende Daten als einzige Source of Truth. Eine Renderfunktion leitet aus dem aktuellen Array eine Anzeige ab. Rufe sie auf, nachdem du das Array oder ein Objekt darin geändert hast.
Ersetze die Anzeige bei jedem Rendern
Angenommen, tasks enthält vier Objekte, von denen genau eines erledigt ist, und Aufgabe 2 existiert und ist unerledigt. Eine Renderfunktion kann neue Einträge und eine Zusammenfassung erstellen:
function render() {
const items = tasks.map(task => {
const li = document.createElement("li");
li.dataset.id = String(task.id);
li.textContent = task.text;
li.classList.toggle("done", task.done);
return li;
});
list.replaceChildren(...items);
const doneCount = tasks.filter(task => task.done).length;
summary.textContent = `${doneCount} of ${tasks.length} done`;
}
Nach tasks.push({ id: 5, text: "Book dentist", done: false }); render(); hat die Liste fünf Einträge und die Zusammenfassung lautet „1 of 5 done“. Das Setzen von tasks.find(task => task.id === 2).done = true; render(); ändert sie zu „2 of 5 done“.
Das Ersetzen der Kindknoten ist hier wesentlich. Würde die Funktion alle Einträge nur anhängen, würde ein zweimaliger Aufruf die Anzeige verdoppeln. Auch das Entfernen nur eines DOM-Eintrags ist vorübergehend: Bleibt sein Objekt im Array, bringt das Rendern ihn zurück. Wenn tasks mit let deklariert ist, lösche mit tasks = tasks.filter(task => task.id !== id) aus den Daten und rendere erneut.
Leite eine Ansicht ab, ohne die Quelle zu verlieren
Übergib bei einer Renderfunktion, die ein Ansichtsarray annimmt, tasks.filter(task => !task.done), um nur unerledigte Aufgaben anzuzeigen. Behalte das vollständige Array für spätere Ansichten und Zählungen über die gesamte Liste. Gib Zusammenfassungen klare Bedeutungen: Die Anzahl sichtbarer Aufgaben unterscheidet sich von der Anzahl aller Aufgaben.
sort() ändert das Array, auf dem es aufgerufen wird. Sortiere für die Anzeige eine Kopie mit [...tasks].sort(...) oder verwende tasks.toSorted(...) für eine sortierte Kopie. Gib eine Vergleichsfunktion an: Numerische Werte benötigen (a, b) => a - b, und für Titel eignet sich (a, b) => a.title.localeCompare(b.title). Die Standardsortierung vergleicht Zeichenkettenformen, sodass [100, 25, 3].sort() in dieser Reihenfolge bleibt; numerisches Sortieren ergibt [3, 25, 100].
Ordne IDs zu und parse Daten korrekt
Eine angezeigte dataset.id ist eine Zeichenkette. Wandle sie vor einem strikten Vergleich mit numerischen IDs um, sonst kann find() den Wert undefined zurückgeben, selbst wenn das gesuchte Objekt existiert. JSON-Daten sind anders: JSON.parse() erhält JSON-Zahlen und boolesche Werte mit diesen Typen. Geparste Objekte können dieselbe Renderfunktion durchlaufen wie direkt im Code geschriebene Objekte.
Erhalte bei Bedarf den lokalen Zustand
Ein vollständiger Neuaufbau erstellt neue Elemente. Dabei können der Fokus und in Eingabefelder innerhalb des neu aufgebauten Bereichs eingegebener Text verloren gehen. Aktualisiere bei einer kleinen Zustandsänderung, bei der diese Objekte erhalten bleiben müssen, zuerst die Daten und dann den vorhandenen Eintrag, etwa mit li.classList.toggle("done", task.done). Die Daten müssen die Änderung weiterhin festhalten, damit ein späteres vollständiges Rendern mit der aktuellen Anzeige übereinstimmt.
Gib Ansicht und Zusammenfassung getrennte Eingaben
Eine gefilterte Ansicht kann weiterhin eine Zusammenfassung aller Aufgaben anzeigen:
function renderOpenTasks() {
const visible = tasks.filter(task => !task.done);
const nodes = visible.map(task => {
const li = document.createElement("li");
li.textContent = task.text;
return li;
});
if (visible.length === 0) {
const empty = document.createElement("li");
empty.textContent = "No open tasks";
nodes.push(empty);
}
list.replaceChildren(...nodes);
const done = tasks.filter(task => task.done).length;
summary.textContent = `${done} of ${tasks.length} done`;
}
Ein Array mit ausschließlich erledigten Aufgaben zeigt für diese Ansicht die Leermeldung, behält aber jedes Objekt für die Gesamtzahl. Eine Zählung aus visible würde eine andere Frage beantworten und könnte keine erledigten Aufgaben melden, nur weil diese Ansicht sie ausschließt.
Wichtige Erkenntnisse
- Aktualisiere die Daten und leite dann die Seite aus diesen Daten ab.
- Ersetze beim Neuaufbau einer Liste alte Kindknoten, um Duplikate zu vermeiden.
- Filtere und sortiere eine abgeleitete Ansicht und erhalte bei Bedarf das ursprüngliche Array.
- Gib für numerisches Sortieren eine Vergleichsfunktion an und wandle dataset-IDs vor numerischen Vergleichen um.
- JSON.parse() erhält numerische und boolesche Datentypen.
- Aktualisiere gezielt ein Element, wenn ein Neuaufbau benötigte Eingabezustände oder den Fokus verlieren würde.
Document Object Model: Beispiele
1Finde dich in einem Seitenbaum zurecht
11 Schritte
- 1EinführungBeginne mit einer Seite, die du untersuchen kannst
Der Browser erstellt Objekte aus HTML. JavaScript arbeitet mit diesem DOM-Baum.
Verfolge eine Liste mit zwei Einträgen vom Markup bis zu den Knoten und nutze dann Familienbeziehungen, um einen benachbarten Eintrag zu erreichen. Halte die DevTools geöffnet, um die sichtbare Seite mit ihrem Baum zu vergleichen.
- 2ErklärungSteige über document ein
Das DOM ist das dynamische Seitenmodell des Browsers.
documentbietet Zugriff;document.bodyverweist auf das Body-Element.Der Browser stellt diese API bereit. JavaScript ruft sie auf, um die aktuelle Seite zu ändern, ohne sie neu zu laden oder die HTML-Datei des Servers umzuschreiben.
- 3BeispielBetrachte das Element und seinen Text getrennt
Betrachte
<li>Buy milk</li>. Das<li>wird zu einem Elementknoten und „Buy milk“ zu einem Textknoten als Kindknoten darin.Lies
nodeType, um sie zu unterscheiden: Das Element hat Typ 1 und sein Textknoten hat Typ 3. Kommentare haben Typ 8 und das Dokument selbst hat Typ 9. „Knoten“ bezeichnet die übergeordnete Gruppe; ein Element ist eine Art von Knoten. - 4BeispielZähle, was die Einrückung hinzufügt
Verwende genau diese Anordnung:
<ul id="tasks"> <li>Buy milk</li> <li>Call Sam</li> </ul>Die Liste hat zwei Kindelemente. Sie hat außerdem drei Textknoten mit Leerraumzeichen: vor, zwischen und nach diesen Einträgen. Ihre
children.lengthist daher 2, währendchildNodes.lengthgleich 5 ist. Die zusätzlichen Knoten entstehen aus den Zeichen zwischen den Tags. - 5HerausforderungBestimme den ersten Knoten
Welche Art von Knoten ist
tasks.firstChildin der eingerückten Liste aus der vorherigen Folie und warum unterscheidet er sich vontasks.firstElementChild?---reveal---
firstChildist der Textknoten mit Leerraumzeichen vor dem ersten Eintrag.firstElementChildüberspringt diesen Knoten und gibt das erste<li>zurück. Die Einrückung beeinflusst die Knotenfolge, obwohl sie keine weitere sichtbare Aufgabe erstellt. - 6TippUntersuche den aktuellen Baum
Wähle beim ersten Listeneintrag „Untersuchen“. Der Bereich „Elemente“ zeigt das aktuelle DOM. Wenn der Eintrag ausgewählt ist, verweist
$0in der Konsole darauf undconsole.dir($0)zeigt seine Eigenschaften.Der Baum kann vom Parser hinzugefügte Elemente enthalten, etwa ein
<tbody>um Tabellenzeilen. Prüfe in diesem Bereich die tatsächliche Verschachtelung, statt anzunehmen, dass sie jeder Tag-Grenze im Quelltext entspricht. - 7BeispielGehe zum nächsten Element
Speichere die Liste als
tasksund folge dann einer Elementbeziehung:const first = tasks.firstElementChild; const second = first.nextElementSibling;second.textContentist „Call Sam“. Das Lesen vonfirst.nextSiblingerreicht dagegen die Leerraumzeichen zwischen den Einträgen. Wähle die Elementform, wenn du zwischen Seitenelementen navigieren und Textknoten überspringen möchtest. - 8ErklärungHalte beim letzten Eintrag sicher an
Das
nextElementSiblingdes letzten Eintrags istnull. Das direkte Lesen einer Eigenschaft von dieser fehlenden Referenz löst einen TypeError aus.second.nextElementSibling?.textContenthält dort an und ergibtundefined, ohne einen Knoten hinzuzufügen oder eine leere Zeichenkette zu liefern. - 9VerbindungFinde den umschließenden Eintrag anhand seiner Bedeutung
Ein verschachteltes span-Element kann seine umschließende Aufgabe mit
span.closest("li")finden. Die Suche beginnt beim span-Element selbst und prüft dann nacheinander Vorfahrenknoten, bis ein Treffer gefunden wird.span.matches("li")prüft nur das span-Element und gibt in diesem Fall false zurück. Eine Suche nach Vorfahrenknoten ist nützlich, wenn ein zusätzliches umschließendes Element dazu führen könnte, dass eine feste Anzahl von Schritten über Elternknoten zur falschen Stelle führt. - 10HerausforderungNavigiere durch ein zusätzliches umschließendes Element
Jeder Listeneintrag umschließt seinen Text nun mit einem span-Element. Wie kannst du ausgehend vom ersten span-Element den Text des nächsten Eintrags lesen, ohne von Leerraumknoten oder der Anzahl umschließender Elemente innerhalb eines Eintrags abhängig zu sein?
---reveal---
Finde den umschließenden Eintrag und dann sein nächstes Geschwisterelement:
span.closest("li").nextElementSibling?.textContent. Der umschließende Eintrag wird über sein Tag gefunden, und die Navigation nur über Geschwisterelemente überspringt die Leerraumzeichen zwischen den Einträgen. - 11ZusammenfassungProbiere als Nächstes eine Tabelle
Untersuche eine Tabelle, deren Quelltext eine Zeile direkt innerhalb von
<table>platziert. Finde den tatsächlichen Elternknoten der Zeile.Vergleiche die Anzahl ihrer Kindknoten und Kindelemente und erkläre anhand des Bereichs „Elemente“ die vom Parser hinzugefügte Struktur und die Leerraumzeichen.
2Wähle die gewünschten Elemente aus und aktualisiere sie
12 Schritte
Speichere diese Einheit, um jede Interaktive Lektion Schritt für Schritt durchzugehen.
- 1EinführungWähle eine Suche, bevor du eine Seite änderst
- 2ErklärungVerwende die passende ID-Syntax für die Methode
- 3BeispielSuche eine wiederholte Klasse innerhalb ihrer Karte
- 4TippUnterscheide einen fehlenden Knoten von falscher Syntax
- 5HerausforderungErkläre ein frühes null-Ergebnis
- 6BeispielDurchlaufe die zurückgegebenen Elemente
- 7ErklärungWandle um, wenn du Arraymethoden benötigst
- 8BeispielVergleiche zwei gespeicherte Sammlungen
- 9KernaussageBeobachte eine schrumpfende dynamische Sammlung
- 10HerausforderungWähle den richtigen kombinierten Selektor
- 11HerausforderungVerbinde einen Suchbereich mit sicherem Durchlaufen
- 12ZusammenfassungUntersuche deine nächste fehlgeschlagene Suche
3Aktualisiere ein Profil und lies seine Formularwerte
15 Schritte
Speichere diese Einheit, um jede Interaktive Lektion Schritt für Schritt durchzugehen.
- 1EinführungUnterscheide die Informationen eines Elements
- 2BeispielLies Text ohne seine Tags
- 3ErklärungBehandle externe Werte als Zeichen
- 4HerausforderungErhalte ein vorhandenes Eingabefeld
- 5VerbindungLies bei Bedarf den gerenderten Text
- 6BeispielLies eine geschriebene oder eine aufgelöste URL
- 7ErklärungSetze einen booleschen Wert über das Vorhandensein
- 8HerausforderungKorrigiere ein deaktiviertes Bedienelement
- 9BeispielWandle einen Datennamen in einen Eigenschaftsnamen um
- 10ErklärungLies den aktuellen Feldinhalt
- 11HerausforderungRechne mit einem Feldwert
- 12BeispielFinde ein Objekt anhand einer angezeigten ID
- 13TippGib einem Symbol-Bedienelement einen lesbaren Namen
- 14HerausforderungVerbinde Datensuche mit sicherer Anzeige
- 15ZusammenfassungUntersuche ein Feld vor und nach der Bearbeitung
4Lass das Aussehen einem klaren Zustand folgen
13 Schritte
Speichere diese Einheit, um jede Interaktive Lektion Schritt für Schritt durchzugehen.
- 1EinführungLass Daten den sichtbaren Zustand bestimmen
- 2BeispielErhalte eine Basisklasse beim Hinzufügen eines Zustands
- 3ErklärungVerwende eine Bedingung für wiederholte Aktualisierungen
- 4HerausforderungBestimme das Ergebnis zweier wiederholter Aktualisierungen
- 5BeispielBerechne einen CSS-Prozentwert
- 6ErklärungLies das Ergebnis der Kaskade
- 7HerausforderungStelle die Farbe des Stylesheets wieder her
- 8ErklärungWähle, was ein geschlossener Bereich entfernt
- 9BeispielStimme einen Bereich und sein Bedienelement aufeinander ab
- 10TippPrüfe einen Stil, der hidden übersteuert
- 11HerausforderungUntersuche ein unsichtbares, aber aktives Bedienelement
- 12HerausforderungKombiniere Klassen mit einem berechneten Wert
- 13ZusammenfassungPrüfe Zustand und Aussehen getrennt
5Erstelle Einträge und verfolge ihre Objektreferenzen
12 Schritte
Speichere diese Einheit, um jede Interaktive Lektion Schritt für Schritt durchzugehen.
- 1EinführungErstelle einen Aufgabeneintrag in einzelnen Schritten
- 2BeispielErstelle einen losgelösten Eintrag
- 3BeispielFüge den fertigen Eintrag ein
- 4ErklärungWähle Kind- oder Geschwisterknoten
- 5BeispielVerschiebe einen bereits vorhandenen Knoten
- 6HerausforderungErkläre ein Schleifenergebnis mit einem Eintrag
- 7ErklärungLöse ein Element, ohne eine Referenz zu verlieren
- 8BeispielErsetze einen Eintrag oder eine ganze Anzeige
- 9TippKopiere Nachfahrenknoten und prüfe IDs
- 10HerausforderungBestimme das Ergebnis einer flachen Kopie
- 11HerausforderungVerschiebe das Original und füge eine Kopie ein
- 12ZusammenfassungVerfolge Identitäten neben dem Markup
6Rendere eine Liste aus Daten und aktualisiere sie zuverlässig
17 Schritte
Speichere diese Einheit, um jede Interaktive Lektion Schritt für Schritt durchzugehen.
- 1EinführungLass das Array die Anzeige bestimmen
- 2BeispielSchreibe eine Erstellungsfunktion für ein Buch
- 3BeispielEntfalte das Array in Knotenargumente
- 4TippHalte fehlende Daten lesbar
- 5VerbindungWende das Muster auf Tabellenzeilen an
- 6HerausforderungFinde heraus, warum die Liste Objekttext zeigt
- 7BeispielSammle Knoten außerhalb der Seite
- 8ErklärungHalte wiederholte Struktur in HTML
- 9BeispielFülle den Klon vor dem Übertragen
- 10HerausforderungErhalte das wiederverwendbare Template
- 11ErklärungErsetze die Anzeige anhand aktueller Daten
- 12BeispielAktualisiere ein Objekt und seine Zusammenfassung
- 13ErklärungHalte eine sortierte Ansicht getrennt
- 14HerausforderungErkläre einen Eintrag, der nach dem Löschen wiederkehrt
- 15KernaussageErhalte den lokalen Eingabezustand
- 16HerausforderungVerbinde eine Suche mit einer gezielten Aktualisierung
- 17ZusammenfassungPrüfe das Rendern in drei Zuständen
Document Object Model: Übungsaufgaben
Set 1: Lies und ändere eine Seite10 Übungsfragen
Frage 1 von 10
Antwort zeigenAntwort ausblenden
Frage 2 von 10
<ul><li>A</li> <li>B</li></ul> enthält eine Variable first den ersten Eintrag. Was gibt first.nextSibling.nodeType zurück?Antwort zeigenAntwort ausblenden
nextElementSibling erreicht. Die Knotennavigation schließt Text zwischen Tags ein; die Elementnavigation überspringt ihn.Frage 3 von 10
<section id="report"> mit getElementById() auswählen?Antwort zeigenAntwort ausblenden
getElementById(). Die Raute gehört zur CSS-Selektorsyntax; die Übergabe von „#report“ sucht hier nach einer ID, die dieses Zeichen enthält, und verfehlt diesen Abschnitt.Frage 4 von 10
flag. Der Code speichert const live = box.getElementsByClassName("flag") und führt dann for (let i = 0; i < live.length; i++) { live[i].classList.remove("flag"); } aus. Welche Elemente behalten die Klasse?Antwort zeigenAntwort ausblenden
Frage 5 von 10
label.textContent = "<em>Saved</em>"?Antwort zeigenAntwort ausblenden
textContent fügt die wörtlichen Zeichen „Saved“ ein. Die Tags werden nicht zu einem Element für Hervorhebung geparst; verwende das Erstellen von Elementen oder das Parsen vertrauenswürdigen HTMLs, wenn eine Struktur beabsichtigt ist.Frage 6 von 10
button.setAttribute("disabled", "false") aus. Welchen Zustand meldet button.disabled?Antwort zeigenAntwort ausblenden
button.disabled wahr. Sein Text „false“ kann ein boolesches Attribut nicht ausschalten; entferne es oder setze die boolesche Eigenschaft auf false, um die Schaltfläche zu aktivieren.Frage 7 von 10
input.value + 2?Antwort zeigenAntwort ausblenden
+ 2 ihn zu „62“. Wandle vor dem Addieren mit Number(input.value) + 2 um, um die Zahl 8 zu erhalten, auch wenn das Feld ein Zahleneingabefeld ist.Frage 8 von 10
class="card compact". Wie kann Code „selected“ hinzufügen und beide vorhandenen Klassen erhalten?Antwort zeigenAntwort ausblenden
classList.add("selected") erhält „card“ und „compact“. Eine Zuweisung der gesamten Klassenzeichenkette ersetzt sie, während ein vorangestellter Punkt Teil des hinzugefügten Tokens statt Selektorsyntax würde.Frage 9 von 10
list.append(list.firstElementChild)?Antwort zeigenAntwort ausblenden
Frage 10 von 10
makeItem() gibt ein neues <li> zurück. Was fügt list.append(records.map(makeItem)) ein, wenn records zwei Einträge hat?Antwort zeigenAntwort ausblenden
map() gibt ein Array zurück und append() erhält dieses Array als ein Argument. Es wandelt das Array in Text mit den Zeichenkettendarstellungen der Elemente um, statt die Knoten einzufügen. Verwende list.append(...records.map(makeItem)), um jedes Element als separates Argument zu übergeben.Set 2: Wähle die richtige DOM-Operation10 Übungsfragen
Speichere diese Einheit, um jede Antwort zu sehen und jedes Set zu üben.
Frage 1 von 10
<table><tr><td>8</td></tr></table>. Welches direkte Kindelement platziert der Parser normalerweise innerhalb der Tabelle?Antwort zeigenAntwort ausblenden
Speichere diese Einheit, um diese Antwort zu sehen.
Frage 2 von 10
<head> wählt eine später im <body> geschriebene Fußzeile aus und erhält null. Der Selektor ist korrekt. Welches Skriptattribut sorgt für die Ausführung nach dem Parsen des HTML?Antwort zeigenAntwort ausblenden
Speichere diese Einheit, um diese Antwort zu sehen.
Frage 3 von 10
.note-Elemente. Eines verliert seine Klasse note und ein neues note-Element wird angehängt. Welche Länge hat die gespeicherte NodeList?Antwort zeigenAntwort ausblenden
Speichere diese Einheit, um diese Antwort zu sehen.
Frage 4 von 10
data-record-id="38". Wie kann Code diese ID mit strikter Gleichheit mit der Zahl 38 vergleichen?Antwort zeigenAntwort ausblenden
Speichere diese Einheit, um diese Antwort zu sehen.
Frage 5 von 10
Antwort zeigenAntwort ausblenden
Speichere diese Einheit, um diese Antwort zu sehen.
Frage 6 von 10
Antwort zeigenAntwort ausblenden
Speichere diese Einheit, um diese Antwort zu sehen.
Frage 7 von 10
container.replaceChildren() auf, setzt a.textContent = "C" und führt dann container.append(a) und container.append(a.cloneNode(true)) aus. Was enthält der Container?Antwort zeigenAntwort ausblenden
Speichere diese Einheit, um diese Antwort zu sehen.
Frage 8 von 10
score: 0. Was zeigt record.score ?? "Pending" bei einer Zuweisung an textContent an?Antwort zeigenAntwort ausblenden
Speichere diese Einheit, um diese Antwort zu sehen.
Frage 9 von 10
Antwort zeigenAntwort ausblenden
Speichere diese Einheit, um diese Antwort zu sehen.
Frage 10 von 10
[{n: 14}, {n: 3}, {n: 9}]. Eine Ansicht soll sie numerisch aufsteigend anzeigen und dabei die Quellreihenfolge erhalten. Welcher Ausdruck erstellt diese Ansicht?Antwort zeigenAntwort ausblenden
Speichere diese Einheit, um diese Antwort zu sehen.
Set 3: Verfolge Knoten, Zustand und Sammlungen10 Übungsfragen
Speichere diese Einheit, um jede Antwort zu sehen und jedes Set zu üben.
Frage 1 von 10
entry und liegt innerhalb eines Abschnitts mit derselben Klasse. Was gibt button.closest(".entry") zurück?Antwort zeigenAntwort ausblenden
Speichere diese Einheit, um diese Antwort zu sehen.
Frage 2 von 10
.mark-Elemente. Code speichert eine dynamische Klassensammlung und eine statische NodeList der passenden Elemente. Er entfernt das erste Mitglied der dynamischen Sammlung und dann die Klasse vom neuen ersten Mitglied dieser Sammlung. Welche Längen haben die dynamische und die statische Sammlung am Ende?Antwort zeigenAntwort ausblenden
Speichere diese Einheit, um diese Antwort zu sehen.
Frage 3 von 10
Antwort zeigenAntwort ausblenden
Speichere diese Einheit, um diese Antwort zu sehen.
Frage 4 von 10
https://example.com/catalog/ steht ein Link als <a href="/guide">Guide</a>. Was gibt link.getAttribute("href") zurück?Antwort zeigenAntwort ausblenden
Speichere diese Einheit, um diese Antwort zu sehen.
Frage 5 von 10
class="row done". Code führt row.classList.toggle("done", false) zweimal aus. Welche Klassen bleiben?Antwort zeigenAntwort ausblenden
Speichere diese Einheit, um diese Antwort zu sehen.
Frage 6 von 10
Antwort zeigenAntwort ausblenden
Speichere diese Einheit, um diese Antwort zu sehen.
Frage 7 von 10
insertAdjacentHTML() eine vertrauenswürdige Notiz als ersten Kindknoten des Abschnitts einfügen?Antwort zeigenAntwort ausblenden
Speichere diese Einheit, um diese Antwort zu sehen.
Frage 8 von 10
Antwort zeigenAntwort ausblenden
Speichere diese Einheit, um diese Antwort zu sehen.
Frage 9 von 10
template.content direkt an eine Liste an. Warum gibt ein späteres template.content.querySelector(".title") null zurück?Antwort zeigenAntwort ausblenden
Speichere diese Einheit, um diese Antwort zu sehen.
Frage 10 von 10
[{id:31, done:true}, {id:32, done:false}, {id:33, done:false}]. Code entfernt nur Zeile 31 aus dem DOM, markiert Aufgabe 32 im Array als erledigt und baut dann alle Zeilen und die Zusammenfassung vollständig aus diesem Array neu auf. Was wird angezeigt?Antwort zeigenAntwort ausblenden
Speichere diese Einheit, um diese Antwort zu sehen.
Set 4: Erstelle zuverlässige datenbasierte Anzeigen10 Übungsfragen
Speichere diese Einheit, um jede Antwort zu sehen und jedes Set zu üben.
Frage 1 von 10
Hello, ein verschachteltes <strong>team</strong> und einen HTML-Kommentar. Ist der Text des strong-Elements ein Geschwisterknoten des Kommentars?Antwort zeigenAntwort ausblenden
Speichere diese Einheit, um diese Antwort zu sehen.
Frage 2 von 10
.status enthalten. Eine Variable main enthält den Hauptbereich. Welche Suche findet dessen erstes status-Nachfahrenelement?Antwort zeigenAntwort ausblenden
Speichere diese Einheit, um diese Antwort zu sehen.
Frage 3 von 10
const field = box.querySelector("input"). Ein Nutzer ändert dieses Eingabefeld von „A“ zu „B“. Das Skript führt box.innerHTML += "<span>Done</span>" und dann field.value = "C" aus. Was passiert mit dem sichtbaren Eingabefeld?Antwort zeigenAntwort ausblenden
Speichere diese Einheit, um diese Antwort zu sehen.
Frage 4 von 10
value="2". Nachdem der Nutzer es zu 7 geändert hat, liest ein Skript Number(input.getAttribute("value")) + 1. Welche Zahl erhält es?Antwort zeigenAntwort ausblenden
Speichere diese Einheit, um diese Antwort zu sehen.
Frage 5 von 10
panel.hidden = true ausgeblendet, aber das CSS enthält .panel { display: grid; } und der Bereich bleibt sichtbar. Sein Bedienelement meldet außerdem weiterhin aria-expanded="true". Was korrigiert beide Zustände für einen geschlossenen Bereich?Antwort zeigenAntwort ausblenden
Speichere diese Einheit, um diese Antwort zu sehen.
Frage 6 von 10
a, führt list.lastElementChild.before(a) und dann list.prepend(list.lastElementChild) aus. Wie lautet die endgültige Reihenfolge?Antwort zeigenAntwort ausblenden
Speichere diese Einheit, um diese Antwort zu sehen.
Frage 7 von 10
author. Welche Zuweisung zeigt „Unknown author“ an, ohne den Wert als HTML zu parsen?Antwort zeigenAntwort ausblenden
Speichere diese Einheit, um diese Antwort zu sehen.
Frage 8 von 10
clone.querySelector(".name").textContent = record.name. Warum schlägt das fehl?Antwort zeigenAntwort ausblenden
Speichere diese Einheit, um diese Antwort zu sehen.
Frage 9 von 10
<li> von ID 12 und rendert dann eine gefilterte Ansicht aus dem unveränderten Array. Der Filter behält alle drei Objekte. Was muss sich ändern, damit ID 12 nach jedem späteren vollständigen Rendern gelöscht bleibt?Antwort zeigenAntwort ausblenden
Speichere diese Einheit, um diese Antwort zu sehen.
Frage 10 von 10
[{"id":24,"done":false}]. Wie unterscheiden sich nach JSON.parse() die Typen von id und done von data-id="24" eines Elements?Antwort zeigenAntwort ausblenden
Speichere diese Einheit, um diese Antwort zu sehen.
Set 5: Finde und behebe Fehler bei DOM-Aktualisierungen10 Übungsfragen
Speichere diese Einheit, um jede Antwort zu sehen und jedes Set zu üben.
Frage 1 von 10
<div class="card"><div class="body"><span class="label">A</span></div></div>. Ausgehend von der Beschriftung verwendet Code parentElement.parentElement, um die Karte zu finden. Zwischen body und label wird ein neues umschließendes Element eingefügt. Welcher Ersatz bleibt zuverlässig?Antwort zeigenAntwort ausblenden
Speichere diese Einheit, um diese Antwort zu sehen.
Frage 2 von 10
snap = list.querySelectorAll(".new") erstellt. Zwei Elemente mit der Klasse new werden angehängt, dann entfernt eine Schleife über snap die Klasse new. Eine neue Klassensuche wird als dynamische Sammlung gespeichert. Wie groß sind snap.length und die Länge der dynamischen Sammlung?Antwort zeigenAntwort ausblenden
Speichere diese Einheit, um diese Antwort zu sehen.
Frage 3 von 10
<script>-Tags heraus. Welche Aktualisierung erhält das Vorschau-Element und fügt den Kommentar ohne HTML-Parsing als wörtlichen Text ein?Antwort zeigenAntwort ausblenden
Speichere diese Einheit, um diese Antwort zu sehen.
Frage 4 von 10
Antwort zeigenAntwort ausblenden
Speichere diese Einheit, um diese Antwort zu sehen.
Frage 5 von 10
class="row selected". Die Daten besagen, dass selected falsch ist. Code führt row.classList.toggle("selected") und später row.classList.toggle("selected", false) aus. Wie lauten die beiden Rückgabewerte und welche Klassen bleiben am Ende?Antwort zeigenAntwort ausblenden
Speichere diese Einheit, um diese Antwort zu sehen.
Frage 6 von 10
Antwort zeigenAntwort ausblenden
Speichere diese Einheit, um diese Antwort zu sehen.
Frage 7 von 10
const open = panel.hidden, setzt panel.hidden = !open und schreibt String(open) in aria-expanded. Wie lauten die endgültigen Zustände?Antwort zeigenAntwort ausblenden
Speichere diese Einheit, um diese Antwort zu sehen.
Frage 8 von 10
<li id="copy-me"><span>Map</span></li> wird mit cloneNode(false) kopiert. Was enthält der losgelöste Klon?Antwort zeigenAntwort ausblenden
Speichere diese Einheit, um diese Antwort zu sehen.
Frage 9 von 10
list.replaceChildren(fragment) auf. Welche Objekte bleiben gefüllt?Antwort zeigenAntwort ausblenden
Speichere diese Einheit, um diese Antwort zu sehen.
Frage 10 von 10
{id: 5, done: false}. Die vorhandene Zeile hat data-id="5" und ein fokussiertes Eingabefeld. Code muss den Datensatz als erledigt markieren, dies durch eine Klasse anzeigen und das Eingabeobjekt erhalten. Welche Abfolge passt?Antwort zeigenAntwort ausblenden
Speichere diese Einheit, um diese Antwort zu sehen.
Hängst du bei deiner eigenen Aufgabe fest? Hausaufgabenhilfe
Schlüsselbegriffe
A
Abgeleitete Ansicht
tasks.filter(task => !task.done) an, ohne erledigte Aufgaben zu verwerfen.append()
item.append(title, button) setzt zwei Kindelemente innerhalb eines Eintrags zusammen, bevor dieser in die Seite eingefügt wird.ARIA-Attribut
aria-label auf „Close dialog“ liefert einen zugänglichen Namen für eine Schaltfläche, die nur ein Symbol zeigt.aria-expanded
aria-expanded="true" melden.Array.from()
Array.from(list.children) ermöglicht einer Schleife zum Entfernen, jedes ursprüngliche Kindelement ohne Indexverschiebungen zu besuchen.Attribut
getAttribute() und setAttribute() gelesen oder geändert werden kann.href eines Links kann „/help“ enthalten, während seine Eigenschaft eine aufgelöste vollständige URL meldet.B
Benutzerdefinierte CSS-Eigenschaft
var() verweisen können."--accent" über style.setProperty(), um Regeln zu ändern, die auf den Akzentwert verweisen.Berechneter Stil
getComputedStyle(title).color kann Rot melden, selbst wenn title.style.color leer ist.Boolesches Attribut
setAttribute("disabled", "false") deaktiviert, weil das Attribut existiert.C
camelCase
backgroundColor.background-color wird in JavaScript als style.backgroundColor geschrieben.checked
checked zu false.classList
classList erhält die vorhandene Klasse „card“ und ihre Grundgestaltung.className
className einer Karte entfernt ihre frühere Klasse „card“, sofern sie nicht erneut aufgenommen wird.closest()
closest(".product") seine umschließende Karte finden.createElement()
document.createElement("li") erstellt einen Listeneintrag, fügt ihn aber noch nicht zur sichtbaren Liste hinzu.Cross-Site-Scripting
textContent für einen eingegebenen Namen verhindert, dass dessen Zeichen zu eingeschleustem Markup werden.CSS-Einheit
CSS-Selektor
"#profile .name" findet Nachfahrenelemente des Profilelements mit der Klasse name.D
dataset
row.dataset.recordId = "26" erstellt oder ändert das Attribut data-record-id.Datenattribut
data- beginnt und Informationen für Skripte speichert, ohne sie als Text anzuzeigen.data-id="26" kann dem Objekt zugeordnet werden, das ihre angezeigten Felder geliefert hat.defer-Attribut
display: none
Document Object Model
DocumentFragment
DOM-Element
<ul>-Element kann zwei <li>-Kindelemente sowie Textknoten mit Leerraumzeichen enthalten.Dynamische Sammlung
E
Eigenschaft
disabled gibt einen booleschen Wert zurück, während das Lesen eines Attributs eine Zeichenkette oder null zurückgibt.Elternknoten
<ul><li>Read</li></ul> ist die Liste der unmittelbare Elternknoten des Eintragselements.Entwicklerwerkzeuge (DevTools)
$0 zur Verfügung.Erzwungene Klassenumschaltung
row.classList.toggle("done", task.done) hält die Zeile über wiederholte Rendervorgänge hinweg konsistent.G
Gebündeltes Einfügen
replaceChildren(...items).Geschwisterknoten
getElementById()
document.getElementById("result") sucht nach der ID „result“ ohne vorangestellte Raute.Gezielte Aktualisierung
H
hidden
panel.hidden = false, um einen ausgeblendeten Bereich anzuzeigen, ohne seinen Inhalt neu aufzubauen.HTMLCollection
list.children zurückgegebenen Sammlung.I
In-place-Sortierung
[...items], bevor du sort() aufrufst, wenn die Quellreihenfolge unverändert bleiben muss.Inline-Stil
bar.style.width = "60%" speichert eine berechnete Fortschrittsbreite direkt am Balken.innerHTML
"<strong>Ready</strong>" erstellt ein neues strong-Element innerhalb des Containers.innerText
innerText einer sichtbaren Beschriftung lässt eine verschachtelte Notiz aus, die mit display: none gestaltet ist.insertAdjacentHTML()
insertBefore()
list.insertBefore(newItem, list.firstElementChild) setzt den Eintrag vor das erste Kindelement.K
Kindknoten
Klassentoken
classList.add(), damit keines der Token ein Leerzeichen enthält.Knoten
L
Leerzustand
Losgelöster Knoten
N
NodeList
querySelectorAll() zurückgegebene NodeList enthält passende Elemente.Array.from() um, bevor du die Arraymethode map() verwendest.null
Nullish-Coalescing-Operator
?? nur dann einen Ersatzwert, wenn der linke Wert null oder undefined ist, und lässt andere Werte unverändert.book.author ?? "Unknown author" liefert lesbaren Text, wenn der optionale Autor fehlt.O
opacity: 0
outerHTML
P
Parsen
<tbody>-Element einfügen.prepend()
Q
querySelector()
null, wenn keines passt..name an anderer Stelle zum Ergebnis wird.R
Renderfunktion
Rendern
replaceChildren()
replaceWith()
S
Source of Truth
Spread-Syntax
list.append(...items) fügt jeden erstellten Knoten statt der Zeichenkettendarstellung des Arrays ein.Statische Sammlung
querySelectorAll() enthält keinen vierten Eintrag, der nach der ursprünglichen Suche angehängt wurde.T
Tabellenkörper
<tbody>, der die Datenzeilen einer Tabelle gruppiert.<tr> an den ausgewählten Tabellenkörper an und füllt seine Felder in <td>-Zellen.template-Element
Template-Inhalt
template.content, das die nicht angezeigte Kindstruktur des Templates enthält.textContent
Textknoten
Tiefer Klon
toFixed()
toFixed(1) zur Zeichenkette „28.5“.Typumwandlung
Number(row.dataset.id) ermöglicht der strikten Gleichheit, die gespeicherten Ziffern mit einer numerischen Objekt-ID zu vergleichen.V
value
Vergleichsfunktion
(a, b) => a - b ordnet numerische Werte von klein nach groß.visibility: hidden
Vorfahrenknoten
Über diese Einheit
Erstelle deine eigenen Lernmaterialien
Mach aus deinen Notizen, Folien und Dokumenten Lernleitfäden, Übungsfragen, Karteikarten und 6 weitere Tools.