Signatur
Beschreibung
Die Methode addEventListener() des EventTarget-Interfaces registriert eine Funktion, die aufgerufen wird, wann immer das angegebene Ereignis an das Ziel ausgeliefert wird.
Übliche Ziele sind Element oder dessen Kinder, Document und Window, das Ziel kann jedoch jedes Objekt sein, das Events unterstützt (etwa IDBRequest).
Hinweis: Die Methode addEventListener() ist die empfohlene Möglichkeit, einen EventListener zu registrieren. Die Vorteile sind:
- Sie erlaubt es, mehr als einen Handler für ein Event hinzuzufügen. Das ist besonders nützlich für Bibliotheken, JavaScript-Module oder jede andere Art von Code, der gut mit anderen Bibliotheken oder Erweiterungen zusammenarbeiten muss.
- Im Gegensatz zur Nutzung einer
onXYZ-Eigenschaft bietet sie eine feinere Kontrolle über die Phase, in der der Listener aktiviert wird (capturing vs. bubbling). - Sie funktioniert mit jedem Event-Target, nicht nur mit HTML- oder SVG-Elementen.
Die Methode addEventListener() arbeitet, indem sie eine Funktion oder ein Objekt, das eine handleEvent()-Funktion implementiert, zur Liste der EventListener für den angegebenen Event-Typ am EventTarget, auf dem sie aufgerufen wird, hinzufügt. Ist die Funktion oder das Objekt bereits in der Liste der EventListener für dieses Ziel, wird sie nicht ein zweites Mal hinzugefügt.
Hinweis: Befindet sich eine bestimmte anonyme Funktion in der Liste der EventListener, die für ein bestimmtes Ziel registriert sind, und wird später im Code eine identische anonyme Funktion in einem addEventListener-Aufruf angegeben, wird die zweite Funktion ebenfalls zur Liste der EventListener für dieses Ziel hinzugefügt. Tatsächlich sind anonyme Funktionen nicht identisch, selbst wenn sie mit demselben unveränderten Quellcode wiederholt definiert werden, auch nicht in einer Schleife. Dieselbe unbenannte Funktion in solchen Fällen wiederholt zu definieren, kann problematisch sein.
Wird ein EventListener innerhalb eines anderen Listeners – also während der Verarbeitung des Events – zu einem EventTarget hinzugefügt, löst dieses Event den neuen Listener nicht aus. Der neue Listener kann jedoch in einer späteren Phase des Event-Flusses ausgelöst werden, etwa während der Bubbling-Phase.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $type Pflicht | string | — | Ein Groß-/Kleinschreibung beachtender String, der den Event-Typ repräsentiert, auf den gelauscht werden soll. |
| $listener Pflicht | Function | Object | null | — | Das Objekt, das eine Benachrichtigung erhält (ein Objekt, das das Event-Interface implementiert), wenn ein Event des angegebenen Typs auftritt. Dies muss null, ein Objekt mit einer handleEvent()-Methode oder eine JavaScript-Funktion sein. |
| $options | Object | — | Ein Objekt, das Eigenschaften des EventListeners festlegt. Verfügbare Optionen: capture (boolean, default false) – Events dieses Typs werden an den registrierten Listener ausgeliefert, bevor sie an ein darunterliegendes EventTarget im DOM-Baum ausgeliefert werden. once (boolean, default false) – der Listener wird nach dem Hinzufügen höchstens einmal aufgerufen und danach automatisch entfernt. passive (boolean) – zeigt an, dass die durch listener angegebene Funktion niemals preventDefault() aufruft; ruft ein passiver Listener preventDefault() auf, geschieht nichts und es kann eine Konsolenwarnung ausgegeben werden. signal (AbortSignal) – der Listener wird entfernt, wenn die abort()-Methode des zugehörigen AbortController aufgerufen wird. |
| $useCapture | boolean | false | Ein boolescher Wert, der angibt, ob Events dieses Typs an den registrierten Listener ausgeliefert werden, bevor sie an ein darunterliegendes EventTarget im DOM-Baum ausgeliefert werden. Events, die im Baum nach oben bubblen, lösen keinen Listener aus, der Capture verwendet. |
| $wantsUntrusted | boolean | — | Nicht-standardisierter Firefox-(Gecko-)spezifischer Parameter. Bei true erhält der Listener synthetische Events, die von Web-Inhalten ausgelöst werden (Standard ist false für Browser-Chrome und true für reguläre Webseiten). |
Rückgabewert
Beispiele
Einfachen Listener hinzufügen (JavaScript)
// Function to change the content of t2
function modifyText() {
const t2 = document.getElementById("t2");
const isNodeThree = t2.firstChild.nodeValue === "three";
t2.firstChild.nodeValue = isNodeThree ? "two" : "three";
}
// Add event listener to table
const el = document.getElementById("outside");
el.addEventListener("click", modifyText);
Abbrechbaren Listener hinzufügen
// Add an abortable event listener to table
const controller = new AbortController();
const el = document.getElementById("outside");
el.addEventListener("click", modifyText, { signal: controller.signal });
// Function to change the content of t2
function modifyText() {
const t2 = document.getElementById("t2");
if (t2.firstChild.nodeValue === "three") {
t2.firstChild.nodeValue = "two";
} else {
t2.firstChild.nodeValue = "three";
controller.abort(); // remove listener after value reaches "three"
}
}
EventListener mit anonymer Funktion
// Function to change the content of t2
function modifyText(newText) {
const t2 = document.getElementById("t2");
t2.firstChild.nodeValue = newText;
}
// Function to add event listener to table
const el = document.getElementById("outside");
el.addEventListener("click", function () {
modifyText("four");
});
EventListener mit Arrow-Funktion
// Function to change the content of t2
function modifyText(newText) {
const t2 = document.getElementById("t2");
t2.firstChild.nodeValue = newText;
}
// Add event listener to table with an arrow function
const el = document.getElementById("outside");
el.addEventListener("click", () => {
modifyText("four");
});
handleEvent-Callback für mehrere Event-Typen
function handleEvent(event) {
if (event.type === "fullscreenchange") {
/* handle a full screen toggle */
} else {
/* handle a full screen toggle error */
}
}
Wert von "this" innerhalb des Handlers
myElement.addEventListener("click", function (e) {
console.log(this.className); // logs the className of myElement
console.log(e.currentTarget === this); // logs `true`
});
Arrow-Funktion hat kein eigenes this
myElement.addEventListener("click", (e) => {
console.log(this.className); // WARNING: `this` is not `myElement`
console.log(e.currentTarget === this); // logs `false`
});
this per bind() festlegen
class Something {
name = "Something Good";
constructor(element) {
// bind causes a fixed `this` context to be assigned to `onclick2`
this.onclick2 = this.onclick2.bind(this);
element.addEventListener("click", this.onclick1);
element.addEventListener("click", this.onclick2); // Trick
}
onclick1(event) {
console.log(this.name); // undefined, as `this` is the element
}
onclick2(event) {
console.log(this.name); // 'Something Good', as `this` is bound to the Something instance
}
}
const s = new Something(document.body);
handleEvent-Methode nutzen
class Something {
name = "Something Good";
constructor(element) {
// Note that the listeners in this case are `this`, not this.handleEvent
element.addEventListener("click", this);
element.addEventListener("dblclick", this);
}
handleEvent(event) {
console.log(this.name); // 'Something Good', as this is bound to newly created object
switch (event.type) {
case "click":
// some code here…
break;
case "dblclick":
// some code here…
break;
}
}
}
const s = new Something(document.body);
Arrow-Funktion für this-Bindung
class SomeClass {
name = "Something Good";
register() {
window.addEventListener("keydown", (e) => {
this.someMethod(e);
});
}
someMethod(e) {
console.log(this.name);
switch (e.code) {
case "ArrowUp":
// some code here…
break;
case "ArrowDown":
// some code here…
break;
}
}
}
const myObject = new SomeClass();
myObject.register();
Daten in und aus einem EventListener übergeben
const myButton = document.getElementById("my-button-id");
let someString = "Data";
myButton.addEventListener("click", () => {
console.log(someString);
// 'Data' on first click,
// 'Data Again' on second click
someString = "Data Again";
});
console.log(someString); // Expected Value: 'Data' (will never output 'Data Again')
Speicherprobleme
const elems = document.getElementsByTagName("*");
// Case 1
for (const elem of elems) {
elem.addEventListener("click", (e) => {
// Do something
});
}
// Case 2
function processEvent(e) {
// Do something
}
for (const elem of elems) {
elem.addEventListener("click", processEvent);
}
Beispiel für options-Nutzung (JavaScript)
const outer = document.querySelector(".outer");
const middle = document.querySelector(".middle");
const inner1 = document.querySelector(".inner1");
const inner2 = document.querySelector(".inner2");
const capture = {
capture: true,
};
const noneCapture = {
capture: false,
};
const once = {
once: true,
};
const noneOnce = {
once: false,
};
const passive = {
passive: true,
};
const nonePassive = {
passive: false,
};
outer.addEventListener("click", onceHandler, once);
outer.addEventListener("click", noneOnceHandler, noneOnce);
middle.addEventListener("click", captureHandler, capture);
middle.addEventListener("click", noneCaptureHandler, noneCapture);
inner1.addEventListener("click", passiveHandler, passive);
inner2.addEventListener("click", nonePassiveHandler, nonePassive);
function onceHandler(event) {
log("outer, once");
}
function noneOnceHandler(event) {
log("outer, none-once, default\n");
}
function captureHandler(event) {
// event.stopImmediatePropagation();
log("middle, capture");
}
function noneCaptureHandler(event) {
log("middle, none-capture, default");
}
function passiveHandler(event) {
// Unable to preventDefault inside passive event listener invocation.
event.preventDefault();
log("inner1, passive, open new page");
}
function nonePassiveHandler(event) {
event.preventDefault();
// event.stopPropagation();
log("inner2, none-passive, default, not open new page");
}
EventListener mit mehreren Optionen
const buttonToBeClicked = document.getElementById("example-button");
const resetButton = document.getElementById("reset-button");
// the text that the button is initialized with
const initialText = buttonToBeClicked.textContent;
// the text that the button contains after being clicked
const clickedText = "You have clicked this button.";
// we hoist the event listener callback function
// to prevent having duplicate listeners attached
function eventListener() {
buttonToBeClicked.textContent = clickedText;
}
function addListener() {
buttonToBeClicked.addEventListener("click", eventListener, {
passive: true,
once: true,
});
}
// when the reset button is clicked, the example button is reset,
// and allowed to have its state updated again
resetButton.addEventListener("click", () => {
buttonToBeClicked.textContent = initialText;
addListener();
});
addListener();
Scroll-Performance mit passiven Listenern verbessern
const passive = document.querySelector("#passive");
const container = document.querySelector("#container");
passive.addEventListener("change", (event) => {
container.removeEventListener("wheel", wheelHandler);
container.addEventListener("wheel", wheelHandler, {
passive: passive.checked,
once: true,
});
});
container.addEventListener("wheel", wheelHandler, {
passive: true,
once: true,
});
function wheelHandler() {
function isPrime(n) {
for (let c = 2; c <= Math.sqrt(n); ++c) {
if (n % c === 0) {
return false;
}
}
return true;
}
const quota = 1000000;
const primes = [];
const maximum = 1000000;
while (primes.length < quota) {
const candidate = Math.floor(Math.random() * (maximum + 1));
if (isPrime(candidate)) {
primes.push(candidate);
}
}
console.log(primes);
}
// Wichtig · Fallstricke
Der EventListener-Callback: Der EventListener kann entweder als Callback-Funktion oder als Objekt angegeben werden, dessen handleEvent()-Methode als Callback-Funktion dient. Die Callback-Funktion selbst hat dieselben Parameter und denselben Rückgabewert wie die handleEvent()-Methode; das heißt, der Callback akzeptiert einen einzigen Parameter: ein auf Event basierendes Objekt, das das aufgetretene Ereignis beschreibt, und gibt nichts zurück.
Der Wert von "this" innerhalb des Handlers: Beim Anhängen einer Handler-Funktion an ein Element mittels addEventListener() ist der Wert von this innerhalb des Handlers eine Referenz auf das Element. Er ist derselbe wie der Wert der currentTarget-Eigenschaft des an den Handler übergebenen Event-Arguments. Arrow-Funktionen haben keinen eigenen this-Kontext.
Speicherprobleme: Wird bei jeder Iteration einer Schleife eine neue anonyme Handler-Funktion erzeugt, führt dies zu höherem Speicherverbrauch, und removeEventListener() kann nicht aufgerufen werden, da keine Referenz auf die anonymen Funktionen gehalten wird. Die Verwendung einer statischen Funktionsreferenz löst beide Probleme.
Passive Listener: Durch Setzen von passive auf true erklärt ein EventListener, dass er die Standardaktion nicht abbrechen wird, sodass der Browser diese sofort starten kann. Moderne Browser (außer Safari) setzen den Standardwert von passive für wheel-, mousewheel-, touchstart- und touchmove-Events auf Dokument-Ebene (Window, Document, Document.body) auf true. Um dieses Verhalten zu übersteuern, muss passive: false explizit gesetzt werden.