Asynchrone Ereignisse
addEventListener registriert Events wie »Laden der Webseite abgeschlossen«, den Klick auf ein Element, die Antwort auf einen Fetch-Request oder das Laden eines Videos und ruft eine Funktion (die auch als Event Handler bezeichnet wird) auf, sobald das Event feuert.
elem.addEventListener( eventType, // EventType (z.B. click, touch o. mouseover) handler, // aufzurufende Funktion useCapture); // Phase der Aktivierung
addEventListener ist asynchron: Das Skript ruft den Event Listener auf, bevor das Ereignis stattfindet, damit er Aktionen in Gang setzt, sobald das Ereignis erkannt wird. Bis es soweit ist, arbeitet der Browser die Seite ab und wartet nicht auf das Eintreten des Events. Das ist das Asynchrone an der Eventsteuerung: Während das Script auf das Laden eines Bildes wartet, kann es weitere Anweisungen wie z.B. Berechnungen durchführen.
const elem = document.getElementById('elem'); elem.addEventListener ('click', myFunction, false); elem.addEventListener ('touch', myFunction, false); … nächste Anweisung …
Der Aufruf von addEventListener meldet theoretisch beliebig viele Events für ein Element an, aber muss für jedes Event individuell aufgerufen werden: Darum ein Aufruf für ein click-Event und ein Aufruf für das touch-Event.
Der Handler ist im einfachsten Fall eine Javascript-Funktion, in der die Aktionen durchgeführt werden.
<div id="elem"> … </div> let elem = document.getElementById('elem'); elem.addEventListener ('click', showElem, false); function showElem() { … }
Der dritte Parameter von addEventListener – useCapture – legt fest, in welcher Phase ein Event einen Event Listener aktiviert. Die Vorgabe ist false.
EventListener – Argumente
- type
- Art des Ereignisses, das überwacht werden soll (z.B. click, touch, load, change, input …)
- listener
- Event-Handler, die Funktion, die beim Eintreten des Ereignis aufgerufen werden soll
- options (Boolean)
- Ereignisse wie ein Klick auf einen Button betreffen nicht nur den Button, sondern auch »darunter liegende« Elemente wie einen umgebenden div-Block.
Wenn ein solcher Vorfahre das Event ebenfalls beobachtet, kann er vor (true ) oder nach dem Button (false) benachrichtigt werden.
Wir ziehen heute fast immer false (bubble) vor. Für moderne Skripte macht es selten Sinn, ein Event von mehreren Event Handlern behandeln zu lassen. Wenn der Benutzer auf ein Element klicken, erwartet er eine Aktion auf diesem Element. Darum wird jedes Event in einem eigenen Skript behandelt.
Das war die lange Erklärung für: Kann man meistens weglassen. - options (Objekt)
-
- capture (Boolean) false (bubble – aufsteigend) oder true (capture – abfangen) wie options 1
- once (Boolean) EventListener wird automatisch nach dem Auslösen entfernt
- passive (Boolean) wenn der EventListener niemals preventDefault() aufruft.
- signal (AbortSignal) ein Signal, das die Registrierung des EventListeners abbricht
In der alltäglichen Anwendung eines Buttons, der bei einem Klick eine Aktion auslösen soll:
<div class="simpleResult"></div> <button class="btn" id="simpleButton">Klick!</button>
const simpleButton = document.querySelector("#simpleButton"); Element Event EventHandler-Funktion │ │ │ ▼ ▼ ▼ simpleButton.addEventListener("click", function() { document.querySelector(".simpleResult").innerHTML += "Geschafft!" });
Der EventListener des Buttons horcht auf das click-Event und gibt einen Text aus. Die EventHandler-Funktion ist eine anonyme Funktion, das dritte Argument wird nicht genutzt. Nach einem Klick ist der EventListener weiterhin in Kraft.
removeEventListener
Der EventListener bleibt aktiv und horcht weiter auf das Eintreten des Event, auch wenn das Event ein erstes Mal eingetreten ist. Für einige Arten von Events ist das auch so erwünscht (z.B. bei click-Events), für andere Events hingegen kann dieses Verhalten zu Fehlern führen (z.B. bei einem mouseover).
Darum gibt es eine passende Methode removeEventListener, der das Event aus der Warteschlange der gemeldeten Events herausnimmt.
element.addEventListener("mouseover", function handler (event) { … event.currentTarget.removeEventListener(event.type, handler); });
Event Handler-Funktion mit Argumenten
Wenn die Handler-Funktion Argumente braucht, müssen die Anweisungen als anonyme Funktion in den Aufruf der Funktion addEventListener geschrieben werden.
elem.addEventListener ('click',
function() { //<-----anonyme Funktion
showElem(param1, param2)
},
false);
function showElem(p1, p2) {
…
}
Typische Argumente des Event Listeners sind z.B. das Element, auf dem ein Event ausgelöst wird. Wenn ein Klick-Event für drei verschiedene Buttons registriert werden kann, muss das Script u.U. erkennen, auf welchem Button das Event stattgefunden hat. Dafür bringen Events Informationen wie Event Target / Event Type (Ziel des Events und Art des Events) mit.
addEventListener mit callback-Funktion
Wenn die behandelnde Funktion aufwändiger wird oder von weiteren Anweisungen gebraucht wird, ist eine Callback-Funktion sinnvoll. Da hier gleich eine ganze Gruppe von Elementen vorliegt, braucht die Funktion das auslösende Event als Argument. In diesem einfachen Akkordeon identifiziert event.target das Element, auf dem Event bei einem Klick ausgelöst wird.
<div class="demo"> <div class="box boxAni"></div> <div class="box"></div> <div class="box"></div> <div class="box"></div> </div>
function handleStackMove (event) { const elem = event.target; document.querySelector(".boxAni").classList.remove("boxAni"); elem.classList.add("boxAni"); } const boxen = document.querySelectorAll(".box"); boxen.forEach ((item) => { item.addEventListener ("click", handleStackMove) });
Zu beachten ist, dass die Funktion handleStackMove() zwar mit runden Klammern und event als Argument deklariert, aber ohne runde Klammern aufgerufen wird. Das Event wird dabei automatisch inherent übergeben. Über das Event wiederum erkennt die Funktion handleStackMove(), welches Element behandelt werden soll.
Eine elegante Methode, die den Kontext (z.B. welches Element wurde hier geklickt?) zur behandelnden Funktion transpartieren kann, ist function.bind().
addEventListener once
In den immergrünen Browsern (alles außer IE11) hat addEventListener eine zusätzliche Option once, die den Event Listener automatisch entfernt, wenn das Event einmal eingetreten ist.
elem.addEventListener('click', function (event) {
// nur einmal auszuführen
}, {once: true});
Das Aufräumen und Ausschalten der Event Handler, die nur einmal anspringen sollen, hält den Code übersichtlicher und die Speicherverwaltung effizienter, denn alle Variablen, die zum Callback gehören, können gelöscht werden (Garbage Collector).
Das »Element geladen?«-Problem
An einem generellen Problem ändert auch der eventListener des W3C nichts: addEventListener kann den Handler erst ausführen, wenn das HTML-Element im Browser geladen wurde.
Javascript wird darum heute entweder im Kopf der Seite mit dem defer- bzw. async-Attribut geladen, oder aber am Ende des Dokuments vor dem schließenden body-Tag. So ist sicher gestellt, dass die angesprochenen Elemente geladen sind. Aber auch wenn der Browser ein img-Tag bereits verarbeitet hat, ist das angesprochene Bild noch nicht geladen.
Wird ein Ereignis-Handler registriert, bevor der Browser das HTML-Element geladen hat, kommt es zu einem JavaScript-Fehler: Das Objekt ist unbekannt.