JavaScript DOM Manipulation
JavaScript DOM Manipulation: Inhalte mit textContent und innerHTML ändern, Attribute und Klassen bearbeiten, Elemente erstellen, einfügen, klonen und entfernen – mit praktischen Beispielen.
JavaScript DOM (Document Object Model) Manipulation ist eine grundlegende Fähigkeit für Webentwickler. Der DOM ist eine lebendige, baumförmige Darstellung der Seite, die der Browser aus Ihrem HTML aufbaut; ihn zu manipulieren bedeutet, JavaScript zu verwenden, um diesen Baum zur Laufzeit zu lesen und zu verändern, sodass die Seite sich ohne Neu laden aktualisiert.
Dieser Leitfaden behandelt die vier Operationen, die Sie am häufigsten benötigen:
- Inhalte lesen und ändern mit
textContentundinnerHTML. - Attribute lesen und ändern mit
getAttribute,setAttributeundclassList. - Elemente erstellen und einfügen mit
createElement,append,insertBeforeundinsertAdjacentHTML. - Elemente entfernen und ersetzen mit
remove()undreplaceWith().
Bevor Sie ein Element manipulieren können, müssen Sie es zunächst finden. Falls Sie mit getElementById, querySelector und verwandten Methoden noch nicht vertraut sind, lesen Sie zuerst DOM-Elemente auswählen und Suchen: getElement, querySelector — alle folgenden Beispiele setzen voraus, dass Sie bereits eine Referenz auf den Knoten haben.
Elementinhalt und Attribute ändern
Das Manipulieren von Inhalt und Attributen von DOM-Elementen ist ein wesentlicher Aspekt der dynamischen Webentwicklung. Durch das Ändern des Inhalts können wir den Text oder das HTML innerhalb eines Elements aktualisieren. Durch das Ändern von Attributen können wir Eigenschaften wie class, id oder src modifizieren. JavaScript bietet leistungsstarke Methoden, um diese Aufgaben zu erledigen, und ermöglicht uns die Entwicklung responsiver, interaktiver Webanwendungen. Schauen wir uns an, wie man innerHTML, textContent, setAttribute und getAttribute effektiv einsetzt.
Elementinhalt ändern
Wir können den Inhalt eines Elements mit den Eigenschaften innerHTML oder textContent ändern.
innerHTML vs textContent
innerHTML erlaubt es uns, den HTML-Inhalt eines Elements zu setzen oder abzurufen, einschließlich aller HTML-Tags.
<!DOCTYPE html>
<html>
<head>
<title>innerHTML vs textContent</title>
<style>
.content-container {
margin: 20px;
padding: 10px;
border: 1px solid #ccc;
border-radius: 5px;
}
.html-content {
color: red;
}
</style>
</head>
<body>
<div class="content-container">
<p id="content">Original paragraph content.</p>
<button id="change-innerHTML">Change using innerHTML</button>
<button id="change-textContent">Change using textContent</button>
</div>
<script>
const content = document.getElementById('content');
const innerHTMLButton = document.getElementById('change-innerHTML');
const textContentButton = document.getElementById('change-textContent');
innerHTMLButton.addEventListener('click', () => {
content.innerHTML = 'New content with <strong class="html-content">HTML</strong> tags.';
});
textContentButton.addEventListener('click', () => {
content.textContent = 'Updated paragraph content without HTML tags.';
});
</script>
</body>
</html>Erklärung:
innerHTMLerlaubt es uns, den HTML-Inhalt eines Elements zu setzen oder abzurufen, einschließlich aller HTML-Tags. Im Beispiel ersetzt ein Klick auf die Schaltfläche „Change using innerHTML" den Absatzinhalt durch neuen Inhalt mit HTML-Tags, was die Darstellung des Textes verändert.textContentsetzt oder ruft den Textinhalt eines Elements ab, ohne HTML-Tags zu verarbeiten. Ein Klick auf die Schaltfläche „Change using textContent" ersetzt den Absatzinhalt durch reinen Text und ignoriert dabei alle HTML-Tags.
Verwenden Sie textContent, wenn Sie benutzergenerierte Inhalte einfügen, um Sicherheitsrisiken wie XSS (Cross-Site Scripting) zu vermeiden. Weist man einem innerHTML einen rohen string eines Benutzers zu, kann ein Angreifer <script>-Tags oder Event-Handler-Attribute einschleusen, die auf Ihrer Seite ausgeführt werden. textContent verarbeitet HTML nie syntaktisch, sodass der string unverändert angezeigt wird und immer sicher ist.
Es gibt auch eine dritte Eigenschaft, outerHTML, die das Element und sein eigenes Tag repräsentiert. Eine Zuweisung daran ersetzt das Element vollständig:
// Replace the whole <p> with an <h2>, keeping it in the same position
const p = document.querySelector('p');
p.outerHTML = '<h2>A heading instead</h2>';
// After this, `p` still points at the old, detached node — re-query if you need the new one.Elementattribute ändern
Wir können die Attribute eines Elements mit der Methode setAttribute ändern und mit getAttribute abrufen. Diese Methoden sind nützlich, um Elemente dynamisch basierend auf Benutzerinteraktionen oder anderen Ereignissen zu modifizieren.
<!DOCTYPE html>
<html>
<head>
<title>setAttribute and getAttribute</title>
</head>
<body>
<div id="container" class="initial-class">Container content</div>
<button id="change-attribute">Change Attribute</button>
<button id="get-attribute">Get Attribute</button>
<script>
const container = document.getElementById('container');
const changeAttributeButton = document.getElementById('change-attribute');
const getAttributeButton = document.getElementById('get-attribute');
changeAttributeButton.addEventListener('click', () => {
container.setAttribute('class', 'new-class');
alert('Class attribute changed to "new-class"');
});
getAttributeButton.addEventListener('click', () => {
const className = container.getAttribute('class');
alert(`Current class attribute: ${className}`);
});
</script>
</body>
</html>Erklärung:
setAttribute('attributeName', 'value'): Diese Methode ermöglicht es uns, einen neuen Wert für ein bestimmtes Attribut eines Elements festzulegen. Im Beispiel ändert ein Klick auf die Schaltfläche „Change Attribute" das class-Attribut des<div>von „initial-class" zu „new-class".getAttribute('attributeName'): Diese Methode ruft den aktuellen Wert des angegebenen Attributs ab. Ein Klick auf die Schaltfläche „Get Attribute" zeigt eine Meldung mit dem aktuellen class-Attributwert des<div>.
Verwenden Sie stets setAttribute und getAttribute für benutzerdefinierte Attribute und dynamisch generierte Attribute. Für die Klassen-Manipulation bevorzugen Sie die classList-API unten — sie bearbeitet Klassen einzeln, anstatt den gesamten class-string zu überschreiben.
Attribute vs. Eigenschaften
Eine häufige Quelle der Verwirrung: Ein HTML-Attribut (was im Markup geschrieben steht) ist nicht immer dasselbe wie die DOM-Eigenschaft (der aktuelle Wert auf dem JavaScript-object). getAttribute('value') liest den ursprünglichen Markup-Wert, während input.value liest, was der Benutzer aktuell eingegeben hat. Bei boolean-Attributen ist der Unterschied noch deutlicher — checkbox.getAttribute('checked') spiegelt das Markup wider, während checkbox.checked den aktuellen Zustand widerspiegelt. Als Faustregel gilt: Verwenden Sie Eigenschaften (el.id, el.value, el.checked) für Standard-, häufig wechselnde Werte und setAttribute/getAttribute für benutzerdefinierte data--Attribute oder einmalige Markup-Attribute.
Zum Lesen und Schreiben von data-*-Attributen gibt es eine dedizierte, ergonomische API — die dataset-Eigenschaft:
// <div id="card" data-user-id="42" data-role="admin"></div>
const card = document.getElementById('card');
console.log(card.dataset.userId); // "42" (note: data-user-id → userId)
card.dataset.role = 'editor'; // writes data-role="editor"Klassen mit classList verwalten
classList schaltet einzelne Klassen um, ohne die bereits vorhandenen zu stören:
element.classList.add('new-class'); // add one (or several) classes
element.classList.remove('old-class'); // remove a class
element.classList.toggle('active'); // add if absent, remove if present
element.classList.replace('open', 'shut'); // swap one class for another
console.log(element.classList.contains('active')); // true / falsetoggle akzeptiert ein optionales zweites Argument, um einen Zustand zu erzwingen, was praktisch ist, um eine Klasse mit einer Bedingung zu synchronisieren: el.classList.toggle('valid', isValid). Für tiefergehende Stilarbeiten — einschließlich Lesen und Schreiben der style-Eigenschaft — siehe Arbeiten mit Stilen im DOM.
Elemente hinzufügen und entfernen
Wir können dem DOM neue Elemente hinzufügen oder bestehende Elemente entfernen.
Elemente hinzufügen
Um dem DOM neue Elemente hinzuzufügen, erstellen wir sie zunächst mit der Methode createElement und fügen sie dann mit appendChild an ein bestehendes Element an oder fügen sie mit insertBefore an einer bestimmten Position ein.
createElement(), appendChild(), insertBefore()
<!DOCTYPE html>
<html>
<head>
<title>Adding Elements</title>
</head>
<body>
<div id="task-list">
<h2>Task List</h2>
<ul id="tasks">
<li>Initial task</li>
</ul>
<input type="text" id="new-task" placeholder="New task">
<button id="add-task">Add Task</button>
<button id="insert-before">Insert Before First Task</button>
</div>
<script>
const taskList = document.getElementById('tasks');
const newTaskInput = document.getElementById('new-task');
const addTaskButton = document.getElementById('add-task');
const insertBeforeButton = document.getElementById('insert-before');
addTaskButton.addEventListener('click', () => {
const newTaskText = newTaskInput.value;
if (newTaskText.trim()) {
const newTask = document.createElement('li');
newTask.textContent = newTaskText;
taskList.appendChild(newTask);
newTaskInput.value = '';
}
});
insertBeforeButton.addEventListener('click', () => {
const newTaskText = newTaskInput.value;
if (newTaskText.trim()) {
const newTask = document.createElement('li');
newTask.textContent = newTaskText;
const firstTask = taskList.firstElementChild;
taskList.insertBefore(newTask, firstTask);
}
});
</script>
</body>
</html>Erklärung:
createElement('tagName'): Diese Methode erstellt ein neues Element, das durchtagNameangegeben wird. Zum Beispiel erstelltdocument.createElement('li')ein neues<li>-Element.appendChild(newElement): Diese Methode fügt ein neues Kindelement an ein bestimmtes Elternelement an. Im Beispiel erstellt ein Klick auf die Schaltfläche „Add Task" ein neues Listenelement (<li>) und fügt es der Aufgabenliste (<ul>) hinzu.insertBefore(newElement, referenceElement): Diese Methode fügt ein neues Element vor einem bestimmten Referenzelement innerhalb desselben Elternelements ein. Ein Klick auf die Schaltfläche „Insert Before First Task" erstellt ein neues Listenelement (<li>) und fügt es vor der ersten Aufgabe in der Liste ein.
Zum direkten Einfügen von HTML-strings sollten Sie insertAdjacentHTML() in Betracht ziehen. Um ein bestehendes Element zu ersetzen, ist element.replaceWith(newElement) eine moderne Alternative zur Kombination aus remove() und appendChild().
insertAdjacentHTML und die modernen Einfüge-Methoden
Wenn Sie bereits einen HTML-string haben (anstatt eines Knotens, den Sie mit createElement erstellt haben), verarbeitet und fügt insertAdjacentHTML(position, html) ihn in einem einzigen Aufruf ein. Das Argument position ist eines von vier Schlüsselwörtern relativ zum Element:
// Given: <div id="box">content</div>
const box = document.getElementById('box');
box.insertAdjacentHTML('beforebegin', '<p>before the box</p>'); // before <div>
box.insertAdjacentHTML('afterbegin', '<p>first child</p>'); // inside, at the start
box.insertAdjacentHTML('beforeend', '<p>last child</p>'); // inside, at the end
box.insertAdjacentHTML('afterend', '<p>after the box</p>'); // after </div>Moderne Browser bieten auch append(), prepend(), before() und after(), die entweder Knoten oder einfache strings akzeptieren und mehrere Argumente auf einmal entgegennehmen können — sie sind in der Regel klarer als appendChild/insertBefore:
const list = document.getElementById('tasks');
const item = document.createElement('li');
item.textContent = 'New task';
list.append(item, 'some trailing text'); // append node + string together
list.prepend('Top of the list'); // insert at the startElemente klonen
Um einen vorhandenen Knoten zu duplizieren, anstatt ihn von Grund auf neu zu erstellen, verwenden Sie cloneNode(deep). Übergeben Sie true, um das Element zusammen mit allen seinen Nachkommen zu kopieren; übergeben Sie false (oder nichts), um nur das Element selbst zu kopieren:
const template = document.getElementById('card');
const copy = template.cloneNode(true); // deep clone, including children
copy.id = 'card-2'; // ids must stay unique
document.body.append(copy);Für wiederholtes, komplexes Markup ist das <template>-Element das dafür vorgesehene Werkzeug — sein Inhalt ist inaktiv, bis Sie ihn einklonen.
Elemente entfernen
Um ein Element zu entfernen, können wir die moderne Methode element.remove() verwenden.
<!DOCTYPE html>
<html>
<head>
<title>Removing Elements</title>
</head>
<body>
<div id="container">
<p id="paragraph">This is a paragraph.</p>
<button id="remove-paragraph">Remove Paragraph</button>
</div>
<script>
const container = document.getElementById('container');
const paragraph = document.getElementById('paragraph');
const removeParagraphButton = document.getElementById('remove-paragraph');
removeParagraphButton.addEventListener('click', () => {
paragraph.remove();
});
</script>
</body>
</html>Erklärung:
element.remove(): Diese moderne Methode entfernt ein bestimmtes Element direkt aus dem DOM. Im Beispiel entfernt ein Klick auf die Schaltfläche „Remove Paragraph" das<p>-Element von der Seite.
Die Verwendung von element.remove() ist der empfohlene Ansatz für dynamische Inhaltsänderungen, wie z. B. das Entfernen von Artikeln aus einem Warenkorb, da sie eine sauberere Syntax bietet als die veraltete Methode parent.removeChild(child) (die nach wie vor nützlich ist, wenn Sie eine Referenz auf den entfernten Knoten benötigen).
Viele Elemente effizient einfügen
Jedes Mal, wenn Sie einen Knoten in das aktive Dokument einfügen, muss der Browser möglicherweise das Layout neu berechnen und neu zeichnen. Dies innerhalb einer Schleife zu tun — einmal pro Element — ist ineffizient. Ein DocumentFragment ermöglicht es Ihnen, Knoten außerhalb des Bildschirms zusammenzubauen und sie alle in einem einzigen Vorgang einzufügen:
const list = document.getElementById('tasks');
const fragment = document.createDocumentFragment();
for (let i = 1; i <= 1000; i++) {
const li = document.createElement('li');
li.textContent = `Task ${i}`;
fragment.appendChild(li); // no layout work — fragment is not in the document
}
list.appendChild(fragment); // one insertion, one reflowZwei verwandte Faustregeln halten DOM-intensiven Code schnell: Bündeln Sie Ihre Lese- und Schreibvorgänge (wechseln Sie nicht zwischen dem Lesen von offsetHeight und dem Setzen von Stilen, da dies zu wiederholten Reflows zwingt) und bevorzugen Sie es, einen string aufzubauen und innerHTML einmal zuzuweisen, anstatt viele kleine appendChild-Aufrufe zu machen, wenn Sie keine Event-Listener an jeden Knoten anhängen. Für eine ausführliche Behandlung siehe DOM Performance Optimization.
Beispiel: Dynamische To-Do-Liste
Lassen Sie uns eine einfache To-Do-Listen-Anwendung erstellen, um die oben genannten Konzepte zu demonstrieren.
<!DOCTYPE html>
<html>
<head>
<title>To-Do List</title>
</head>
<body>
<div id="todo-list">
<h2>My To-Do List</h2>
<ul id="tasks">
<li>Learn JavaScript</li>
</ul>
<input type="text" id="new-task" placeholder="New task">
<button id="add-task">Add Task</button>
</div>
<script>
const taskList = document.getElementById('tasks');
const newTaskInput = document.getElementById('new-task');
const addTaskButton = document.getElementById('add-task');
addTaskButton.addEventListener('click', () => {
const newTaskText = newTaskInput.value;
if (newTaskText.trim()) {
const newTask = document.createElement('li');
newTask.textContent = newTaskText;
taskList.appendChild(newTask);
newTaskInput.value = '';
}
});
taskList.addEventListener('click', (event) => {
if (event.target.tagName === 'LI') {
event.target.remove();
}
});
</script>
</body>
</html>Erklärung:
createElementerstellt ein neues Listenelement für die Aufgabe, undappendChildfügt es der Liste hinzu.- Ein einziger Klick-Listener wird an das
<ul>angehängt, nicht an jedes<li>. Da Klicks vom angeklickten Element zu seinen Vorfahren nach oben weitergegeben werden, prüft der Listenerevent.target, um zu entscheiden, welche Aufgabe angeklickt wurde, und entfernt sie. Dieses Muster wird als Event-Delegation bezeichnet und ist der Grund, warum der Handler auch für Aufgaben funktioniert, die beim Laden der Seite noch nicht existierten.
Event-Delegation ist der Grund, warum wir nicht jedes Mal einen separaten Listener hinzufügen, wenn eine Aufgabe erstellt wird — ein Listener auf dem Elternelement verwaltet aktuelle und zukünftige Kinder. Um tiefer in Bubbling, event.target vs. event.currentTarget und Delegation einzutauchen, lesen Sie Event Handling im DOM.
Wenn eine Benutzeroberfläche viele unabhängige, häufig wechselnde Zustandsteile umfasst, wird das manuelle Synchronisieren des DOM fehleranfällig. Frameworks wie React, Vue oder Svelte ermöglichen es Ihnen, zu beschreiben, wie die Benutzeroberfläche für einen gegebenen Zustand aussehen soll, und übernehmen die DOM-Aktualisierungen für Sie. Die manuellen Techniken in diesem Kapitel bleiben das Fundament, auf dem diese Frameworks aufgebaut sind.
Fazit
Die Beherrschung der DOM-Manipulation ist unerlässlich für die Erstellung dynamischer und interaktiver Webanwendungen. Sie wissen jetzt, wie Sie Inhalte ändern (textContent, innerHTML, outerHTML), mit Attributen und Klassen arbeiten (setAttribute, dataset, classList), Knoten erstellen und einfügen (createElement, append, insertAdjacentHTML, cloneNode), sie entfernen und ersetzen (remove(), replaceWith()) und Einfügungen effizient mit einem DocumentFragment bündeln.
Um auf diesen Grundlagen weiter aufzubauen:
- DOM-Elemente auswählen — finden Sie die Knoten, die Sie ändern möchten.
- Den DOM durchlaufen — bewegen Sie sich zwischen Elternelementen, Kindelementen und Geschwisterelementen.
- Arbeiten mit Stilen im DOM — lesen und schreiben Sie CSS mit JavaScript.
- Event Handling im DOM — reagieren Sie auf Benutzerinteraktionen.