Auch in Zeiten von React, Vue und Svelte ist ein tiefgreifendes Verständnis der nativen DOM-Manipulation unerlässlich. Sie bildet das Fundament, auf dem moderne Frameworks operieren, ist essenziell für die Entwicklung eigener Web-Components und bleibt die effizienteste Wahl für schlanke Vanilla-JavaScript-Projekte. Die heutigen DOM-APIs sind erstaunlich mächtig und elegant – oft ist eine externe Library wie jQuery gar nicht mehr nötig.
Elemente effizient selektieren
// Einzelelement abrufen
const header = document.querySelector('.header');
const submitBtn = document.getElementById('submit-btn');
const firstArticle = document.querySelector('article:first-of-type');
// Mehrere Elemente auswählen (NodeList)
const cards = document.querySelectorAll('.card');
const links = document.querySelectorAll('nav a');
// NodeList bequem iterieren
cards.forEach(card => {
card.classList.add('loaded');
});
// In ein Array umwandeln für erweiterte Array-Methoden
const cardArray = [...document.querySelectorAll('.card')];
const visibleCards = cardArray.filter(c => !c.hidden);
Elemente manipulieren
const el = document.querySelector('.hero-title');
// Textinhalt setzen (sicher vor XSS)
el.textContent = 'Hallo, Welt!';
// HTML-Inhalt setzen (⚠️ XSS-Gefahr bei Benutzereingaben)
el.innerHTML = '<strong>Hallo</strong>, Welt!';
// Attribute steuern
el.setAttribute('role', 'heading');
el.getAttribute('data-id');
el.removeAttribute('hidden');
// Dataset (data-*-Attribute für saubere Datenbindung)
el.dataset.userId = '123'; // Setzt data-user-id="123"
console.log(el.dataset.userId); // "123"
// Klassenmanagement
el.classList.add('active', 'visible');
el.classList.remove('loading');
el.classList.toggle('dark-mode');
el.classList.contains('active'); // true/false
el.classList.replace('old-class', 'new-class');
// Inline-Styles
el.style.color = '#6366f1';
el.style.setProperty('--accent', '#22d3ee');
Elemente dynamisch erstellen & einfügen
// Element erzeugen
const card = document.createElement('div');
card.className = 'card';
card.innerHTML = `
<h3>${title}</h3>
<p>${description}</p>
`;
// In den DOM einfügen
container.appendChild(card); // Am Ende
container.prepend(card); // Am Anfang
container.insertBefore(card, referenceElement); // Vor einem Referenzelement
// Moderne Einfüge-Methoden
element.before(newElement); // Direkt davor
element.after(newElement); // Direkt danach
element.replaceWith(newElement); // Ersetzen
// Element entfernen
element.remove();
// Element duplizieren
const clone = template.cloneNode(true); // true = tiefe Kopie inkl. Kinder
Event-Handling
const button = document.querySelector('#submit');
// Event-Listener hinzufügen
button.addEventListener('click', (event) => {
event.preventDefault();
console.log('Geklickt!', event.target);
});
// Listener entfernen (Referenz auf benannte Funktion nötig)
function handleClick(e) { /* ... */ }
button.addEventListener('click', handleClick);
button.removeEventListener('click', handleClick);
// Wichtige Events
element.addEventListener('click', handler);
element.addEventListener('input', handler); // Änderungen in Echtzeit
element.addEventListener('change', handler); // Bei Fokusverlust
element.addEventListener('submit', handler); // Formular-Absendung
element.addEventListener('keydown', handler); // Tastendruck
element.addEventListener('scroll', handler); // Bildlauf
element.addEventListener('load', handler); // Ressource fertig geladen
Event-Delegation
Anstatt jedem einzelnen Kind-Element einen Listener zuzuweisen, nutzen Sie das Prinzip der Event-Delegation. Registrieren Sie einen zentralen Listener beim Elternelement und identifizieren Sie das Ziel über event.target. Dies ist speicherschonender und funktioniert auch mit Elementen, die erst nachträglich dynamisch in den DOM eingefügt wurden.
// ❌ Nicht effizient: Listener für jedes einzelne Element
document.querySelectorAll('.card').forEach(card => {
card.addEventListener('click', handleCardClick);
});
// ✅ Professionell: Ein einziger Listener am Container
document.querySelector('.card-grid').addEventListener('click', (e) => {
const card = e.target.closest('.card');
if (!card) return; // Klick war außerhalb einer Card
const id = card.dataset.id;
handleCardClick(id);
});
Verwendung des Template-Elements
<!-- Template bleibt im DOM verborgen -->
<template id="card-template">
<div class="card">
<h3 class="card-title"></h3>
<p class="card-desc"></p>
</div>
</template>
<script>
const template = document.getElementById('card-template');
function addCard(title, desc) {
const clone = template.content.cloneNode(true);
clone.querySelector('.card-title').textContent = title;
clone.querySelector('.card-desc').textContent = desc;
document.querySelector('.grid').appendChild(clone);
}
</script>
Performance-Tipps
- DOM-Updates bündeln – nutzen Sie
DocumentFragmentoder bauen Sie Strings lokal zusammen, bevor Sie diese einfügen. - Event-Delegation nutzen statt massenhaft einzelne Event-Listener zu registrieren.
- Layout Thrashing vermeiden – vermeiden Sie es, in einer Schleife abwechselnd Layout-Eigenschaften zu lesen (z.B.
offsetHeight) und zu schreiben (z.B.style.height). requestAnimationFrameverwenden, um visuelle Updates synchron mit der Bildwiederholrate auszuführen.- Events drosseln (Debouncing) – Scroll- oder Resize-Events feuern extrem häufig; begrenzen Sie deren Ausführung.
Entdecke unsere kostenlosen JS-Tools
Optimiere, minifiziere oder formatiere deinen Code mit einem Klick.