Was ist das DOM? JavaScript und HTML verbinden
Verstehe das Document Object Model (DOM) und wie JavaScript mit HTML-Elementen interagiert. Die Grundlage für interaktive Webseiten.
Was ist das DOM?
Das DOM (Document Object Model) ist die Brücke zwischen JavaScript und HTML. Es ermöglicht dir, Webseiten dynamisch zu verändern – Elemente hinzufügen, entfernen, Styles ändern und auf Benutzeraktionen reagieren.
Das DOM verstehen
Wenn der Browser eine HTML-Datei lädt, erstellt er daraus eine Baumstruktur – das DOM:
<!DOCTYPE html>
<html>
<head>
<title>Meine Seite</title>
</head>
<body>
<h1>Hallo Welt</h1>
<p>Ein Absatz</p>
</body>
</html>
Wird zu diesem Baum:
document
└── html
├── head
│ └── title
│ └── "Meine Seite"
└── body
├── h1
│ └── "Hallo Welt"
└── p
└── "Ein Absatz"
Jedes HTML-Element wird zu einem Node (Knoten) im DOM. JavaScript kann jeden dieser Knoten lesen und verändern.
Das document-Objekt
document ist dein Einstiegspunkt ins DOM:
// Das gesamte HTML-Dokument
console.log(document);
// Der <html>-Tag
console.log(document.documentElement);
// Der <head>-Tag
console.log(document.head);
// Der <body>-Tag
console.log(document.body);
// Der Titel der Seite
console.log(document.title);
document.title = "Neuer Titel!"; // Ändert den Browser-Tab
Elemente finden
getElementById
Findet ein Element anhand seiner ID:
<h1 id="main-title">Willkommen!</h1>
const title = document.getElementById("main-title");
console.log(title); // Das H1-Element
console.log(title.textContent); // "Willkommen!"
querySelector (Empfohlen!)
Findet das erste Element, das zum CSS-Selektor passt:
// Nach ID
const title = document.querySelector("#main-title");
// Nach Klasse
const button = document.querySelector(".btn-primary");
// Nach Tag
const firstParagraph = document.querySelector("p");
// Komplexe Selektoren
const navLink = document.querySelector("nav a.active");
const input = document.querySelector('input[type="email"]');
const firstItem = document.querySelector("ul > li:first-child");
querySelectorAll
Findet alle Elemente, die zum Selektor passen:
// Alle Paragraphen
const paragraphs = document.querySelectorAll("p");
console.log(paragraphs.length); // Anzahl
// Durch alle iterieren
paragraphs.forEach((p, index) => {
console.log(`Paragraph ${index}: ${p.textContent}`);
});
// Alle Buttons mit Klasse
const buttons = document.querySelectorAll(".btn");
// In Array umwandeln (für Array-Methoden)
const buttonsArray = [...document.querySelectorAll(".btn")];
Element-Eigenschaften lesen
<a href="https://example.com" id="link" class="btn primary" data-id="123">
Klick mich
</a>
const link = document.querySelector("#link");
// Text-Inhalt
console.log(link.textContent); // "Klick mich"
// Attribute
console.log(link.href); // "https://example.com"
console.log(link.id); // "link"
console.log(link.className); // "btn primary"
// Dataset (data-* Attribute)
console.log(link.dataset.id); // "123"
// Klassen
console.log(link.classList); // ["btn", "primary"]
Elemente verändern
Text ändern
const title = document.querySelector("h1");
// Text setzen (sicher!)
title.textContent = "Neuer Titel!";
Attribute ändern
const link = document.querySelector("a");
// Attribut setzen
link.href = "https://newsite.com";
link.setAttribute("target", "_blank");
// Attribut lesen
console.log(link.getAttribute("href"));
// Attribut entfernen
link.removeAttribute("target");
// Attribut prüfen
if (link.hasAttribute("href")) {
console.log("Hat href!");
}
Klassen manipulieren
const element = document.querySelector(".box");
// Klasse hinzufügen
element.classList.add("active");
element.classList.add("highlight", "visible"); // Mehrere
// Klasse entfernen
element.classList.remove("active");
// Klasse togglen (an/aus)
element.classList.toggle("active");
// Prüfen ob Klasse existiert
if (element.classList.contains("active")) {
console.log("Ist aktiv!");
}
// Klasse ersetzen
element.classList.replace("old-class", "new-class");
Styles ändern
const box = document.querySelector(".box");
// Einzelne Styles
box.style.backgroundColor = "blue";
box.style.color = "white";
box.style.padding = "20px";
// Achtung: CSS-Eigenschaften in camelCase!
// background-color → backgroundColor
// font-size → fontSize
// Besser: Klassen verwenden!
box.classList.add("highlighted");
Elemente erstellen
Neues Element erstellen
// Element erstellen
const newDiv = document.createElement("div");
// Inhalt setzen
newDiv.textContent = "Ich bin neu!";
newDiv.className = "card";
newDiv.id = "new-card";
// Attribute setzen
newDiv.setAttribute("data-id", "123");
// Zum DOM hinzufügen
document.body.appendChild(newDiv);
Komplexere Elemente
function createCard(title, description) {
const card = document.createElement("div");
card.className = "card";
const cardTitle = document.createElement("h3");
cardTitle.textContent = title;
const cardDesc = document.createElement("p");
cardDesc.textContent = description;
const cardButton = document.createElement("button");
cardButton.textContent = "Mehr erfahren";
cardButton.className = "btn";
// Zusammenbauen
card.appendChild(cardTitle);
card.appendChild(cardDesc);
card.appendChild(cardButton);
return card;
}
// Verwenden
const container = document.querySelector("#cards");
container.appendChild(createCard("Titel 1", "Beschreibung 1"));
container.appendChild(createCard("Titel 2", "Beschreibung 2"));
Elemente einfügen & entfernen
Einfügen
const container = document.querySelector("#container");
const newElement = document.createElement("div");
// Am Ende einfügen
container.appendChild(newElement);
// Am Anfang einfügen
container.prepend(newElement);
// Vor einem Element
const reference = document.querySelector("#reference");
container.insertBefore(newElement, reference);
// Moderne Methoden
container.append(newElement); // Am Ende
container.prepend(newElement); // Am Anfang
reference.before(newElement); // Vor Element
reference.after(newElement); // Nach Element
Entfernen
const element = document.querySelector("#to-remove");
// Modern
element.remove();
// Klassisch (über Parent)
element.parentNode.removeChild(element);
// Alle Kinder entfernen
while (container.firstChild) {
container.removeChild(container.firstChild);
}
DOM Navigation
Von einem Element zu anderen navigieren:
const item = document.querySelector(".item");
// Eltern
item.parentNode; // Direkter Elternknoten
item.parentElement; // Elternelement
item.closest(".container"); // Nächster Vorfahre mit Selektor
// Kinder
item.children; // Alle Kind-Elemente
item.firstElementChild; // Erstes Kind-Element
item.lastElementChild; // Letztes Kind-Element
// Geschwister
item.nextElementSibling; // Nächstes Element
item.previousElementSibling; // Vorheriges Element
Praktisches Projekt: Todo-Liste UI
<div id="todo-app">
<input type="text" id="todo-input" placeholder="Neue Aufgabe...">
<button id="add-btn">Hinzufügen</button>
<ul id="todo-list"></ul>
</div>
const input = document.querySelector("#todo-input");
const addBtn = document.querySelector("#add-btn");
const list = document.querySelector("#todo-list");
function createTodoItem(text) {
const li = document.createElement("li");
li.className = "todo-item";
const span = document.createElement("span");
span.textContent = text;
const deleteBtn = document.createElement("button");
deleteBtn.textContent = "Löschen";
deleteBtn.className = "delete-btn";
// Delete-Funktion
deleteBtn.addEventListener("click", () => {
li.remove();
});
// Abhaken durch Klick
span.addEventListener("click", () => {
li.classList.toggle("completed");
});
li.appendChild(span);
li.appendChild(deleteBtn);
return li;
}
function addTodo() {
const text = input.value.trim();
if (text === "") {
input.focus();
return;
}
const todoItem = createTodoItem(text);
list.appendChild(todoItem);
input.value = "";
input.focus();
}
// Event Listeners
addBtn.addEventListener("click", addTodo);
input.addEventListener("keypress", (e) => {
if (e.key === "Enter") {
addTodo();
}
});
Performance-Tipps
1. Selektoren cachen
// Schlecht - jedes Mal suchen
for (let i = 0; i < 100; i++) {
document.querySelector("#container").appendChild(createItem());
}
// Gut - einmal suchen
const container = document.querySelector("#container");
for (let i = 0; i < 100; i++) {
container.appendChild(createItem());
}
2. DocumentFragment für viele Elemente
const list = document.querySelector("#list");
const fragment = document.createDocumentFragment();
for (let i = 0; i < 100; i++) {
const li = document.createElement("li");
li.textContent = `Item ${i}`;
fragment.appendChild(li); // Kein Reflow
}
list.appendChild(fragment); // Ein Reflow
3. Klassen statt Inline-Styles
// Schlecht - mehrere Reflows
element.style.width = "100px";
element.style.height = "100px";
// Gut - ein Reflow
element.classList.add("red-box");
Zusammenfassung
| Methode | Beschreibung |
|---|---|
querySelector() | Ein Element finden |
querySelectorAll() | Alle Elemente finden |
createElement() | Element erstellen |
appendChild() | Element hinzufügen |
remove() | Element entfernen |
classList.add/remove/toggle() | Klassen ändern |
textContent | Text lesen/setzen |
setAttribute() | Attribut setzen |
Übung: Baue die Todo-Liste nach und erweitere sie um eine “Alle löschen”-Funktion!