W3docs

JavaScript Benutzerdefinierte Ereignisse auslösen

Erfahren Sie, wie Sie mit CustomEvent und dispatchEvent eigene Ereignisse in JavaScript erstellen, Daten über detail übergeben und Komponenten entkoppeln.

Benutzerdefinierte Ereignisse in JavaScript auslösen

Der Browser löst eingebaute Ereignisse wie click, submit und keydown automatisch aus. Doch JavaScript ermöglicht es Ihnen auch, eigene Ereignisse auf einem beliebigen DOM-Knoten zu erstellen und auszulösen, und dann mit demselben addEventListener() darauf zu lauschen, den Sie bereits für native Ereignisse verwenden.

Dies ist die Grundlage locker gekoppelten Anwendungsdesigns: Ein Teil Ihres Codes kündigt an, dass etwas passiert ist ("Daten geladen", "Warenkorb aktualisiert"), ohne zu wissen oder sich darum zu kümmern, wer zuhört. Diese Seite erklärt, wie Sie benutzerdefinierte Ereignisse mit dem CustomEvent-Konstruktor erstellen, Daten daran anhängen, sie mit dispatchEvent() auslösen und häufige Fallstricke vermeiden.

Ein benutzerdefiniertes Ereignis erstellen

Verwenden Sie den CustomEvent-Konstruktor. Das erste Argument ist der Ereignis-Typ (der Name, auf den Sie später lauschen werden); das zweite ist ein Options-object:

let event = new CustomEvent("myEvent", {
  detail: { message: "This is a custom event!" },
  bubbles: true,
  cancelable: true
});

Die drei Optionen, die Sie am häufigsten verwenden werden, sind:

  • detail — ein beliebiger Wert (object, string, Zahl), den Sie an das Ereignis anhängen möchten. Der Listener liest ihn als event.detail zurück. Dies ist der dedizierte Kanal für benutzerdefinierte Daten; native Ereigniseigenschaften sind schreibgeschützt.
  • bubbles — wenn true, wandert das Ereignis nach dem Auslösen durch übergeordnete Elemente nach oben, sodass ein Listener auf einem Elternelement (oder document) es abfangen kann. Standardmäßig false.
  • cancelable — wenn true, kann ein Listener event.preventDefault() aufrufen, um zu signalisieren, dass die Standardaktion übersprungen werden soll. Standardmäßig false.

CustomEvent vs. Event

Es gibt auch einen einfachen Event-Konstruktor, der jedoch keine Daten transportieren kann — er hat kein detail. Greifen Sie immer auf CustomEvent zurück, wenn Sie Informationen zusammen mit dem Ereignis weitergeben müssen:

// No way to attach data here:
let bare = new Event("ping", { bubbles: true });

// Use CustomEvent to send a payload:
let withData = new CustomEvent("ping", {
  bubbles: true,
  detail: { at: Date.now() }
});

Das Ereignis auslösen

Ein erstelltes Ereignis tut nichts, bis Sie es auf einem Element mit dispatchEvent() auslösen:

let target = document.getElementById("box");
target.dispatchEvent(event);

Zwei Dinge sind bei dispatchEvent() wissenswert:

  1. Es läuft synchron — anders als setTimeout werden die Listener sofort ausgeführt, bevor die Zeile nach dispatchEvent() läuft.
  2. Es gibt einen boolean zurück: false, wenn das Ereignis cancelable war und ein Listener preventDefault() aufgerufen hat, andernfalls true. Dies ermöglicht es dem Code, der das Ereignis ausgelöst hat, auf ein "Veto" zu reagieren:
let cancelled = !target.dispatchEvent(event);
if (cancelled) {
  console.log("A listener prevented the default action.");
}

Sie können auf jedem Element auslösen. Das Auslösen auf document funktioniert, weil bubblende Ereignisse es erreichen, aber das Auslösen auf dem spezifischen Element, das das Ereignis "besitzt" (und es hochblasen lassen), hält Ihre Listener eingegrenzt und vermeidet versehentliche globale Handler.

Auf ein benutzerdefiniertes Ereignis lauschen

Auf der Lauscher-Seite gibt es keine spezielle API — addEventListener() funktioniert genauso wie für click. Die Daten kommen über event.detail an:

element.addEventListener("myEvent", function (event) {
  console.log(event.detail.message); // "This is a custom event!"
});

Praktische Beispiele

Beispiel 1: Kommunikation zwischen Komponenten

Angenommen, zwei unabhängige Teile einer Seite müssen miteinander kommunizieren, ohne direkte Referenzen aufeinander zu halten. Einer löst ein benutzerdefiniertes Ereignis aus; der andere lauscht. Da das Ereignis bubbles, kann der Listener auf document sitzen:

<button id="sender">Send Message</button>
// Listener in another component
document.addEventListener('componentMessage', function(event) {
  alert('Received message: ' + event.detail.message);
});

document.getElementById('sender').addEventListener('click', function() {
  // Create and dispatch the custom event
  let customEvent = new CustomEvent('componentMessage', {
    detail: { message: 'Hello from another component!' },
    bubbles: true,
    cancelable: true
  });
  document.dispatchEvent(customEvent);
});

So funktioniert es:

  • Ein Klick auf die Schaltfläche erstellt und löst ein componentMessage-Ereignis aus, das eine Nachricht in detail enthält.
  • Ein Listener an anderer Stelle fängt das Ereignis ab und reagiert darauf. Keine Seite importiert die andere — der Ereignisname ist der einzige Vertrag.

Beispiel 2: Die Benutzeroberfläche nach einer Datenänderung aktualisieren

Benutzerdefinierte Ereignisse ermöglichen es Ihnen, Datenlogik von Rendering-Logik zu trennen. Die Datenschicht kündigt dataUpdated an; die UI-Schicht lauscht und rendert neu. Hier wird die Aktualisierung nach einer kurzen Verzögerung ausgelöst, um einen asynchronen Abruf zu simulieren:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Custom Event UI Update Example</title>
</head>
<body>
<h1>User Status</h1>
<div id="userInfo">Loading user information...</div>

<script>
  // Function to simulate a data update
  function updateData() {
    let dataUpdateEvent = new CustomEvent('dataUpdated', {
      detail: { data: { username: 'user123', status: 'active' } }
    });
    document.dispatchEvent(dataUpdateEvent);
  }

  // UI component listening for data updates
  document.addEventListener('dataUpdated', function(event) {
    let userData = event.detail.data;
    document.getElementById('userInfo').innerHTML =
      `Username: <strong>${userData.username}</strong>, Status: <strong>${userData.status}</strong>`;
  });

  // Trigger the update after 2 seconds
  setTimeout(updateData, 2000);
</script>
</body>
</html>

So funktioniert es:

  • Nach zwei Sekunden löst updateData() ein dataUpdated-Ereignis mit den neuen Daten in detail aus.
  • Der UI-Listener liest event.detail.data und aktualisiert die Seite. Die Funktion, die die Daten produziert hat, berührt das DOM nie direkt.

Ein benutzerdefiniertes Ereignis abbrechen

Wenn ein Ereignis cancelable ist, kann ein Listener preventDefault() aufrufen. Der Dispatcher sieht dann den Rückgabewert false von dispatchEvent() und kann sein Standardverhalten überspringen — dasselbe Muster, das der Browser für die Formularübermittlung oder Link-Klicks verwendet. Dieses Snippet läuft in Node und demonstriert den synchronen Ablauf:

let target = new EventTarget();

target.addEventListener("save", (event) => {
  // Veto the save
  event.preventDefault();
});

let event = new CustomEvent("save", { cancelable: true });
let notCancelled = target.dispatchEvent(event);

console.log(notCancelled);          // false
console.log(event.defaultPrevented); // true

EventTarget ist die Basisschnittstelle, von der DOM-Knoten erben, sodass dieselbe Logik gilt, egal ob Sie auf einem Element im Browser oder einem eigenständigen EventTarget auslösen.

Fazit

Benutzerdefinierte Ereignisse bieten Ihnen eine saubere, framework-freie Möglichkeit, Teile einer Anwendung miteinander zu verbinden. Erstellen Sie sie mit CustomEvent, hängen Sie eine Nutzlast über detail an, lösen Sie sie mit dispatchEvent() aus und lauschen Sie mit dem vertrauten addEventListener(). Setzen Sie bubbles: true, wenn ein Elternelement das Ereignis abfangen soll, und cancelable: true, wenn der Dispatcher das Veto eines Listeners berücksichtigen muss. Das Ergebnis ist Code, bei dem Module über benannte Ereignisse statt über direkte Referenzen kommunizieren — einfacher zu testen, zu erweitern und zu warten.

Für weitere Informationen lesen Sie, wie Ereignisse durch das DOM wandern, unter Bubbling und Capturing, wie Listener angehängt werden unter Ereignisbehandlung im DOM, und wie preventDefault() Browser-Standardaktionen beeinflusst.

Übungen

Übung
Welche Aussagen über benutzerdefinierte Ereignisse in JavaScript sind korrekt?
Welche Aussagen über benutzerdefinierte Ereignisse in JavaScript sind korrekt?
Was this page helpful?