Event-Handling im DOM
JavaScript-Events im DOM: addEventListener, removeEventListener, das Event-Objekt, preventDefault, Event-Bubbling und Event-Delegation mit ausführbaren Beispielen.
Einführung in JavaScript-Events
JavaScript-Events sind Aktionen oder Ereignisse, die im Browser auftreten — ein Klick, ein Tastendruck, das Fertigladen einer Seite —, auf die der Code reagieren kann. Die Reaktion auf Events verwandelt eine statische Seite in eine interaktive Anwendung.
Dieses Kapitel behandelt die drei Möglichkeiten, Event-Handler zu registrieren, die häufigsten Event-Typen, das event-Objekt, das jeder Handler erhält, wie Events den DOM durchlaufen (Bubbling und Capturing) sowie die Muster, die event-lastige Seiten schnell und speicherleckfrei halten.
Drei Wege zur Event-Behandlung
Bevor wir uns mit konkreten Events befassen, ist es hilfreich zu wissen, dass es drei verschiedene Möglichkeiten gibt, einen Handler zu registrieren. Sie sind vom ältesten zum flexibelsten aufgeführt.
| Ansatz | Beispiel | Mehrere Handler? | Empfohlen |
|---|---|---|---|
| Inline-HTML-Attribut | <button onclick="doX()"> | Nein | Nein — mischt Markup und Logik |
| DOM-Eigenschaft | element.onclick = fn | Nein (letzter gewinnt) | Nur für einfache Fälle |
addEventListener() | element.addEventListener("click", fn) | Ja | Ja — der moderne Standard |
<button id="propBtn">Click me</button>
<script>
const btn = document.getElementById("propBtn");
// 1. DOM property — assigning again overwrites the previous handler
btn.onclick = function () {
alert("Handled by the onclick property");
};
// 2. addEventListener — adds without overwriting; you can attach many
btn.addEventListener("click", function () {
console.log("Also handled by addEventListener");
});
</script>Beide Handler oben werden bei einem Klick ausgeführt. Wenn btn.onclick ein zweites Mal zugewiesen wird, geht die erste Zuweisung stillschweigend verloren — das ist der Hauptgrund, warum addEventListener() bevorzugt wird. Der Rest dieses Kapitels verwendet addEventListener().
Häufige Events in JavaScript
Click-Event
Das Click-Event wird ausgelöst, wenn der Benutzer die primäre Maustaste über einem Element drückt und loslässt (oder auf Touch-Geräten tippt). Es ist das am häufigsten verwendete Event.
<button id="clickButton">Click Me</button>
<script>
document.getElementById("clickButton").addEventListener("click", function () {
alert("Button was clicked!");
});
</script>In diesem Beispiel wird einem Button mit der ID clickButton ein Event-Listener hinzugefügt. Wenn der Button geklickt wird, erscheint ein Alert-Fenster mit der Meldung "Button was clicked!".
Mouseover-Event
Das Mouseover-Event wird ausgelöst, wenn der Mauszeiger über ein Element bewegt wird. (Sein Gegenstück, mouseout, wird ausgelöst, wenn der Zeiger das Element verlässt.)
<p id="mouseoverText">Hover over me!</p>
<script>
document.getElementById("mouseoverText").addEventListener("mouseover", function () {
this.style.color = "red";
});
</script>In diesem Beispiel wird einem Absatz mit der ID mouseoverText ein Event-Listener hinzugefügt. Wenn die Maus über den Absatz bewegt wird, ändert sich dessen Textfarbe zu Rot.
Keydown-Event
Das Keydown-Event wird ausgelöst, wenn der Benutzer eine Taste drückt, während ein Element fokussiert ist. Der Handler erhält ein event-Objekt, dessen Eigenschaft event.key den Wert der Taste enthält.
<input type="text" id="inputField" placeholder="Type something..." />
<script>
document.getElementById("inputField").addEventListener("keydown", function (event) {
alert(`Key pressed: ${event.key}`);
this.value = '';
});
</script>In diesem Beispiel wird einem Eingabefeld mit der ID inputField ein Event-Listener hinzugefügt. Wenn eine Taste gedrückt wird, während das Eingabefeld fokussiert ist, wird die gedrückte Taste in einem Alert-Fenster angezeigt.
Das Event-Objekt
Jeder Handler wird mit einem Argument aufgerufen: dem Event-Objekt. Es beschreibt, was passiert ist, und stellt Methoden zur Steuerung des Events bereit. Die nützlichsten Eigenschaften sind:
event.target— das Element, auf dem das Event tatsächlich ausgelöst wurde (z. B. der genaue geklickte Button).event.currentTarget— das Element, an dem der Listener befestigt ist. Innerhalb einer regulären Funktion entspricht diesthis.event.type— der Event-Name, z. B."click".event.preventDefault()— bricht die Standard-Browser-Aktion ab (einem Link folgen, ein Formular absenden).event.stopPropagation()— verhindert, dass das Event weiter im DOM nach oben weitergegeben wird.
<a id="link" href="https://www.w3docs.com">Visit W3docs</a>
<script>
document.getElementById("link").addEventListener("click", function (event) {
event.preventDefault(); // stop the browser from navigating away
console.log("type:", event.type); // "click"
console.log("target id:", event.target.id); // "link"
});
</script>Hier verhindert preventDefault(), dass die Seite navigiert, sodass stattdessen eigene Logik ausgeführt werden kann — ein gängiges Muster für Single-Page-Apps und benutzerdefinierte Formularvalidierung.
Innerhalb einer Pfeilfunktion wird this nicht an das Element gebunden. Verwende event.currentTarget (oder eine reguläre function), wenn du eine Referenz auf das Element benötigst, an dem der Listener hängt. Sieh dir arrow functions revisited an, um den Grund zu verstehen.
Event-Listener hinzufügen
Die Methode addEventListener()
Die Methode addEventListener() hängt einen Event-Handler an ein Element, ohne bestehende Event-Handler zu überschreiben. Das bedeutet, dass mehrere Listener — sogar für denselben Event-Typ — an ein einzelnes Element angehängt werden können. Die Signatur lautet element.addEventListener(type, handler, options), wobei options das Verhalten feinjustieren kann (once, capture, passive).
<button id="multiEventButton">Click or Hover</button>
<script>
const button = document.getElementById("multiEventButton");
button.addEventListener("click", function () {
alert("Button clicked!");
});
button.addEventListener("mouseover", function () {
button.style.backgroundColor = "lightblue";
});
</script>In diesem Beispiel werden dem Button mit der ID multiEventButton zwei Event-Listener hinzugefügt. Ein Listener löst einen Alert aus, wenn der Button geklickt wird, und der andere ändert die Hintergrundfarbe des Buttons, wenn die Maus darüber bewegt wird.
Verwende addEventListener(), um mehrere Event-Listener an dasselbe Element anzuhängen, ohne bestehende Handler zu überschreiben.
Event-Listener entfernen
Die Methode removeEventListener()
Die Methode removeEventListener() entfernt einen Handler, der mit addEventListener() hinzugefügt wurde. Der Haken dabei: Es muss genau dieselbe Funktionsreferenz übergeben werden, die hinzugefügt wurde — weshalb benannte Funktionen erforderlich sind, um einen Listener später entfernen zu können.
<button id="removeEventButton">Click Me</button>
<script>
function showAlert() {
alert("This will be removed after first click");
}
const button = document.getElementById("removeEventButton");
button.addEventListener("click", showAlert);
button.addEventListener("click", function () {
button.removeEventListener("click", showAlert);
});
</script>In diesem Beispiel wird dem Button mit der ID removeEventButton ein Event-Listener hinzugefügt, der einen Alert auslöst. Ein weiterer Event-Listener wird hinzugefügt, um den Alert-Event-Listener nach dem ersten Klick zu entfernen. Beachte, dass removeEventListener eine Referenz auf genau dasselbe Funktionsobjekt benötigt, das in addEventListener verwendet wurde. Deshalb können anonyme Funktionen nicht nachträglich entfernt werden — jede Deklaration erstellt ein neues, eigenständiges Funktionsobjekt.
Nutze Event-Delegation für bessere Performance, insbesondere wenn mit einer großen Anzahl von Kindelementen gearbeitet wird.
Event-Propagation und Delegation
Wenn ein Event auf einem Element ausgelöst wird, hört es dort nicht auf. Standardmäßig durchläuft es zwei Phasen: zuerst Capturing (von der Spitze des DOM hinunter zum Ziel), dann Bubbling (vom Ziel zurück bis zur Wurzel). Die meisten Handler werden während der Bubbling-Phase ausgeführt, weshalb ein Klick auf einen Button auch einen Click-Listener im übergeordneten <div> erreicht.
Dieses Bubbling ermöglicht Event-Delegation: Anstatt einen Listener an jedes Kindelement anzuhängen, wird ein einziger Listener an ein gemeinsames Elternelement angehängt und event.target ausgelesen, um herauszufinden, welches Kind tatsächlich geklickt wurde.
<ul id="menu">
<li>Home</li>
<li>About</li>
<li>Contact</li>
</ul>
<script>
// One listener handles clicks on any current OR future <li>
document.getElementById("menu").addEventListener("click", function (event) {
if (event.target.tagName === "LI") {
console.log("You clicked:", event.target.textContent);
}
});
</script>Ein einzelner Listener auf dem <ul> behandelt jedes <li>, einschließlich später hinzugefügter — das ist weitaus effizienter, als jedes Element einzeln zu verdrahten. Für einen tieferen Einblick in die Phasen und stopPropagation() siehe bubbling and capturing.
Best Practices
Event-Delegation verwenden
Füge einem Elternelement einen einzigen Event-Listener hinzu, um alle Events der Kindelemente zu verwalten. Das verbessert die Performance und reduziert die Anzahl der Event-Listener.
Anonyme Funktionen als Event-Handler vermeiden
Die Verwendung benannter Funktionen für Event-Handler erleichtert deren späteres Entfernen und verbessert die Lesbarkeit des Codes.
Event-Listener aufräumen
Stelle sicher, dass Event-Listener entfernt werden, wenn sie nicht mehr benötigt werden, um Speicherlecks zu vermeiden und die Performance zu verbessern.
Die Anzahl der Event-Listener minimieren
Hänge Event-Listener an übergeordnete Elemente statt an zahlreiche einzelne Elemente, um den Speicherverbrauch zu reduzieren und die Performance zu verbessern.
Die Option once in addEventListener verwenden
Nutze die Option once, um den Event-Listener automatisch zu entfernen, nachdem er einmal ausgelöst wurde, und so potenzielle Speicherlecks zu verhindern.
button.addEventListener("click", function handler() {
console.log("Triggered once");
}, { once: true });Standard-Aktionen und Propagation gezielt verhindern
Verwende event.preventDefault() und event.stopPropagation() bedacht, um das Event-Verhalten zu steuern, ohne andere Handler zu beeinträchtigen.
Event-Handler entprellen oder drosseln
Verwende Debouncing- oder Throttling-Techniken, um die Performance von Event-Handlern zu optimieren, die häufig ausgelöst werden, wie z. B. Scroll- oder Resize-Events.
Fazit
Die Beherrschung von JavaScript-Events ist entscheidend für die Erstellung dynamischer und interaktiver Webanwendungen. Durch das Verständnis von Events wie click, mouseover und keydown sowie das Hinzufügen und Entfernen von Event-Listenern mit addEventListener() und removeEventListener() lassen sich Benutzerinteraktionen auf Webseiten erheblich verbessern.