JavaScript DOM-Manipulationstechniken
JavaScript DOM-Manipulation: Elemente erstellen, einfügen, ersetzen und entfernen sowie Optimierungen mit Batching, Document Fragments und Node-Klonen für weniger Reflows.
DOM (Document Object Model) Manipulation ist ein zentraler Aspekt der Webentwicklung, mit dem Sie dynamische, interaktive Seiten erstellen können, indem Sie die Struktur, den Inhalt und das Styling des Dokuments über JavaScript verändern. Dieser Leitfaden beginnt mit den grundlegenden Techniken zum Erstellen, Einfügen, Ersetzen und Entfernen von Elementen und behandelt anschließend Best Practices und Performance-Optimierungen — Batching, Document Fragments und Node-Klonen —, die diese Änderungen schnell halten.
Wenn Sie noch kein Element ausgewählt haben, beginnen Sie mit dem Auswählen von DOM-Elementen. Um den Baum, den Sie bearbeiten, besser zu verstehen, lesen Sie die DOM-Nodes verstehen.
Grundlegende Manipulationstechniken
Jede Änderung am DOM fällt in eine von vier Kategorien: Nodes erstellen, einfügen, ersetzen oder entfernen.
Elemente erstellen
Verwenden Sie document.createElement(), um ein Element im Speicher aufzubauen, und legen Sie dann Inhalt und Attribute fest, bevor Sie es in die Seite einfügen. Ein erstellter Node ist erst sichtbar, wenn er an das Dokument angehängt wird.
const card = document.createElement('div');
card.className = 'card';
card.textContent = 'Hello, DOM!';
card.setAttribute('data-role', 'greeting');
console.log(card.outerHTML);
// <div class="card" data-role="greeting">Hello, DOM!</div>Bevorzugen Sie textContent gegenüber innerHTML, wenn Sie einfachen Text einfügen — es ist schneller und vermeidet das Sicherheitsrisiko durch das Injizieren von nicht escaptem HTML.
Elemente einfügen
Sobald ein Element vorhanden ist, hängen Sie es mit einer dieser Methoden an:
parent.append(node)— fügt den Node als letztes Kind hinzu (akzeptiert auch einfache Strings).parent.prepend(node)— fügt ihn als erstes Kind hinzu.target.before(node)/target.after(node)— fügt ein Geschwisterelement vor oder nachtargetein.parent.appendChild(node)— die klassische API; hängt einen einzelnen Node an und gibt ihn zurück.parent.insertBefore(node, reference)— fügtnodevor demreference-Kind ein.
const list = document.createElement('ul');
const first = document.createElement('li');
first.textContent = 'First';
list.append(first);
const second = document.createElement('li');
second.textContent = 'Second';
list.append(second);
// Put a new item before the first one.
const top = document.createElement('li');
top.textContent = 'Top';
first.before(top);
console.log(list.children.length); // 3
console.log(list.firstElementChild.textContent); // TopVerwenden Sie insertAdjacentHTML(), um einen HTML-String an einer genauen Position einzufügen, ohne das gesamte übergeordnete Element neu zu parsen:
const wrapper = document.createElement('div');
const box = document.createElement('div');
box.textContent = 'middle';
wrapper.append(box); // box must be in the tree to gain siblings
box.insertAdjacentHTML('beforebegin', '<span>before</span>');
box.insertAdjacentHTML('afterend', '<span>after</span>');
console.log(box.previousElementSibling.textContent); // before
console.log(box.nextElementSibling.textContent); // afterElemente ersetzen und entfernen
oldNode.replaceWith(newNode)— ersetztoldNodedurchnewNodean derselben Stelle.element.remove()— entfernt das Element aus dem DOM.parent.replaceChild(newNode, oldNode)undparent.removeChild(child)— die älteren Entsprechungen.
const parent = document.createElement('div');
const a = document.createElement('p');
a.textContent = 'old';
parent.append(a);
const b = document.createElement('p');
b.textContent = 'new';
a.replaceWith(b);
console.log(parent.innerHTML); // <p>new</p>
b.remove();
console.log(parent.innerHTML); // (empty)Die modernen Methoden (append, prepend, before, after, replaceWith, remove) sind leichter lesbar als die veralteten appendChild/insertBefore/replaceChild/removeChild und akzeptieren gleichzeitig mehrere Nodes und Strings. Greifen Sie zuerst auf diese zurück; verwenden Sie die veraltete API nur, wenn Sie sehr alte Browser unterstützen müssen.
Best Practices für die DOM-Manipulation
Direkten DOM-Zugriff minimieren
Der Zugriff auf den DOM kann langsam sein, da er den Browser dazu veranlassen kann, das Layout neu zu berechnen und Elemente neu zu zeichnen. Um den direkten DOM-Zugriff zu minimieren:
- Fassen Sie DOM-Aktualisierungen zusammen, anstatt viele kleine Aktualisierungen einzeln durchzuführen.
- Verwenden Sie Variablen, um Referenzen auf häufig verwendete Elemente zu speichern.
Event-Handling optimieren
Hängen Sie Event-Handler effizient an:
- Verwenden Sie Event-Delegation, um die Anzahl der Event-Listener zu reduzieren.
- Vermeiden Sie es, zu viele Event-Listener direkt an Elemente anzuhängen.
Nicht benötigte Elemente entfernen
Entfernen Sie Elemente, die nicht mehr benötigt werden, um Speicher freizugeben und die Performance zu verbessern:
- Verwenden Sie die Methoden
removeChildoderremove, um Elemente aus dem DOM zu löschen.
Reflows und Repaints minimieren
Was sind Reflows und Repaints?
- Reflows treten auf, wenn sich das Layout eines Teils der Seite ändert, wodurch der Browser die Positionen und Größen der Elemente neu berechnen muss.
- Repaints entstehen, wenn sich das visuelle Erscheinungsbild von Elementen ändert, ohne das Layout zu beeinflussen (z.B. Farbänderungen).
Techniken zur Minimierung von Reflows und Repaints
Änderungen bündeln
Fassen Sie mehrere Änderungen zusammen, um wiederholte Reflows und Repaints zu vermeiden:
<!DOCTYPE html>
<html>
<head>
<title>Batching Changes</title>
</head>
<body>
<div id="content">Original Content</div>
<button id="update">Update Content</button>
<script>
document.getElementById('update').addEventListener('click', () => {
const content = document.getElementById('content');
content.style.display = 'none'; // Hide element to batch changes
content.innerHTML = 'Updated Content';
content.style.display = 'block'; // Show element after updates
});
</script>
</body>
</html>Dieses Beispiel zeigt, wie Änderungen an einem DOM-Element gebündelt werden, um Reflows und Repaints zu minimieren. Indem das Element vor mehreren Aktualisierungen ausgeblendet und danach wieder eingeblendet wird, lassen sich zwischenzeitliche Reflows und Repaints vermeiden.
CSS-Klassen für Änderungen verwenden
Wenden Sie CSS-Änderungen mithilfe von Klassen an, anstatt Stile direkt zu manipulieren:
<!DOCTYPE html>
<html>
<head>
<title>Use CSS Classes</title>
<style>
.hidden { display: none; }
.highlight { color: red; font-weight: bold; }
</style>
</head>
<body>
<div id="content">Hello World</div>
<button id="toggle">Toggle Highlight</button>
<script>
document.getElementById('toggle').addEventListener('click', () => {
const content = document.getElementById('content');
content.classList.toggle('highlight');
});
</script>
</body>
</html>Dieses Beispiel zeigt, wie CSS-Klassen verwendet werden, um mehrere Stiländerungen auf einmal anzuwenden, was effizienter ist als das Ändern einzelner Style-Eigenschaften. Das Umschalten einer Klasse, die mehrere Stile ändert, hilft, die Anzahl der Reflows und Repaints zu reduzieren.
Document Fragments für bessere Performance
Was ist ein Document Fragment?
Ein Document Fragment ist ein leichtgewichtiger Container, der eine Gruppe von Nodes aufnehmen kann. Er ist nicht Teil des eigentlichen DOM-Baums, was bedeutet, dass Änderungen daran keine Reflows und Repaints auslösen.
Verwenden Sie bei mehreren DOM-Manipulationen DocumentFragment, um Ihre Änderungen zu bündeln und in einem einzigen Vorgang an den DOM anzuhängen. Dieser Ansatz minimiert Reflows und Repaints und verbessert die Performance erheblich.
Beispiel für die Verwendung von Document Fragments
<!DOCTYPE html>
<html>
<head>
<title>Document Fragments</title>
</head>
<body>
<div id="list"></div>
<button id="populate">Populate List</button>
<script>
document.getElementById('populate').addEventListener('click', (event) => {
const fragment = document.createDocumentFragment();
for (let i = 1; i <= 25; i++) {
const item = document.createElement('div');
item.textContent = `Item ${i}`;
fragment.appendChild(item);
}
document.getElementById('list').appendChild(fragment);
event.target.disabled = true; // Disable the button
});
</script>
</body>
</html>Dieses Beispiel erstellt 25 div-Elemente und hängt sie an ein Document Fragment an. Erst nachdem alle Elemente zum Fragment hinzugefügt wurden, wird das Fragment in einem einzigen Schritt an den DOM angehängt. Dieser Ansatz minimiert Reflows und Repaints, indem der DOM nur einmal aktualisiert wird.
Nodes klonen
Die Methode cloneNode()
Die Methode cloneNode() wird verwendet, um eine Kopie eines Nodes zu erstellen. Sie kann den Node selbst oder den Node zusammen mit seinen Kindern klonen.
Einen Node ohne Kinder klonen
<!DOCTYPE html>
<html>
<head>
<title>Cloning Nodes</title>
</head>
<body>
<div id="original">Original Node</div>
<button id="clone">Clone Node</button>
<script>
document.getElementById('clone').addEventListener('click', () => {
const original = document.getElementById('original');
const clone = original.cloneNode(false); // Clone without children
clone.id = 'clone';
clone.textContent = 'Cloned Node';
document.body.appendChild(clone);
});
</script>
</body>
</html>Dieses Beispiel zeigt, wie ein Node ohne seine Kinder mithilfe der Methode cloneNode(false) geklont wird. Der geklonte Node übernimmt die Attribute und den Textinhalt des ursprünglichen Nodes, jedoch nicht seine Kind-Nodes.
Einen Node mit Kindern klonen
<!DOCTYPE html>
<html>
<head>
<title>Cloning Nodes with Children</title>
</head>
<body>
<div id="original">
Original Node
<span>Child Node</span>
</div>
<button id="clone">Clone Node with Children</button>
<script>
document.getElementById('clone').addEventListener('click', () => {
const original = document.getElementById('original');
const clone = original.cloneNode(true); // Clone with children
clone.id = 'clone';
document.body.appendChild(clone);
});
</script>
</body>
</html>Dieses Beispiel zeigt, wie ein Node zusammen mit seinen Kindern mithilfe der Methode cloneNode(true) geklont wird. Der geklonte Node enthält den Inhalt des ursprünglichen Nodes sowie alle seine Nachfahren-Nodes.
Fazit
Effiziente DOM-Manipulation ist entscheidend für leistungsstarke Webanwendungen. Beginnen Sie damit, die grundlegenden Methoden zum Erstellen, Einfügen, Ersetzen und Entfernen von Elementen zu beherrschen, und wenden Sie dann die Optimierungen an: Fassen Sie Ihre Aktualisierungen zusammen, bevorzugen Sie CSS-Klassen gegenüber Inline-Stilen, verwenden Sie DocumentFragment für Masseneinfügungen und klonen Sie Nodes, wenn Sie wiederkehrende Strukturen benötigen. Zusammen halten diese Techniken Ihre Seiten reaktionsfähig, selbst wenn der DOM wächst.
Verwandte Themen
- DOM-Manipulation — ein umfassenderer Überblick über das Lesen und Schreiben des Dokumentbaums.
- Den DOM durchlaufen — zwischen Eltern-, Kind- und Geschwisterelementen navigieren.
- DOM Performance-Optimierung — vertiefen Sie das Thema, wie Sie Manipulationen schnell halten.
- Event-Handling im DOM — Interaktionen effizient verdrahten.