mitmario.dev

Auf ein Ereignis hören

JavaScript Im Browser 3 Min Lesezeit 3 BeispieleLektion 1 von 9

Bis hierhin hat der Kurs Seiten gebaut, die sich beim Laden einmal aufbauen und danach stillstehen. Ab jetzt reagieren sie.

Drei Angaben

Worauf, was, womit
const anzeige = document.getElementById("anzeige");
const knopf = document.getElementById("knopf");

// Die Funktion, die später laufen soll.
function melde() {
  anzeige.textContent = "Es hat geklickt";
  console.log("melde() ist gelaufen");
}

// Worauf: knopf. Was: "click". Womit: melde.
knopf.addEventListener("click", melde);

// Beim Laden ist nichts passiert. Erst der Klick löst aus.
console.log("Anzeige beim Laden:", anzeige.textContent);
console.log("Klick den Knopf auf der Seite.");

knopf.addEventListener("click", melde) beantwortet drei Fragen auf einmal:

Worauf wird gehört: auf knopf. Der Listener hängt an genau diesem Element.

Was soll passiert sein: ein "click". Der Name des Ereignisses steht als Text in Anführungszeichen, und es gibt Dutzende davon. Lektion 12.3 zeigt die, die du wirklich brauchst.

Womit wird darauf geantwortet: mit melde. Diese Funktion legst du hinterlegt bereit, und der Browser ruft sie auf, wenn es so weit ist.

Beim Laden passiert dabei nichts. Das ist der Unterschied zu allem, was der Kurs bisher gemacht hat: Du schreibst keine Anweisung, die ausgeführt wird, sondern hinterlegst eine, die ausgeführt werden kann.

Wer sie ausführt, ist dem Browser dabei egal. Tipp knopf.click() in die Eingabezeile der Console, und melde läuft genauso, als hätte jemand geklickt: In der Console steht melde() ist gelaufen, auf der Seite Es hat geklickt.

Der häufigste Fehler dieser Lektion

Das Klammerpaar zu viel
function setzeRichtig() {
  document.getElementById("richtig").textContent = "geklickt";
}

function setzeFalsch() {
  document.getElementById("falsch").textContent = "geklickt";
}

// Ohne Klammern: die Funktion wird übergeben.
document.getElementById("a").addEventListener("click", setzeRichtig);

// Mit Klammern: sie läuft SOFORT, und übergeben wird ihr
// Rückgabewert. Der ist undefined, also hört niemand zu.
document.getElementById("b").addEventListener("click", setzeFalsch());

// Deshalb steht der zweite Text schon beim Laden da,
// und der Knopf tut danach nichts mehr.
console.log("richtig:", document.getElementById("richtig").textContent);
console.log("falsch:", document.getElementById("falsch").textContent);

addEventListener("click", melde) übergibt die Funktion.

addEventListener("click", melde()) ruft sie auf und übergibt ihr Ergebnis.

Der Unterschied ist ein Klammerpaar, und die Folge ist eine doppelte: Die Funktion läuft sofort einmal, obwohl niemand geklickt hat, und danach nie wieder, denn übergeben wurde undefined.

Genau das steht im zweiten Beispiel nebeneinander: Der zweite Absatz zeigt schon beim Laden geklickt, und der zugehörige Knopf tut danach nichts mehr.

Das ist derselbe Unterschied wie in Lektion 5.7. Eine Funktion ohne Klammern ist ein Wert, den man weitergeben kann. Mit Klammern ist sie ein Aufruf, und übrig bleibt nur, was sie zurückgibt.

Die Eingabezeile der Console zeigt beides nebeneinander, am ersten Beispiel. melde allein getippt antwortet ƒ melde(): das ist der Wert, den addEventListener haben will. melde() antwortet undefined, und nebenbei ist die Funktion gelaufen, ohne dass jemand geklickt hätte. Genau dieses undefined bekommt der Browser bei der Schreibweise mit Klammern als Zuhörer.

Einen Fehler gibt es dabei nicht. Der Browser nimmt undefined als Zuhörer klaglos an. Deshalb prüft die Aufgabe zu dieser Lektion ausdrücklich, dass beim Laden noch nichts passiert ist.

Mehrere Zuhörer sind erlaubt

Mehrere Listener am selben Element
const protokoll = document.getElementById("protokoll");
const knopf = document.getElementById("knopf");

function notiere(text) {
  protokoll.textContent = protokoll.textContent
    ? `${protokoll.textContent}, ${text}`
    : text;
}

// Drei Listener auf demselben Element und demselben Ereignis.
// Alle drei laufen, in der Reihenfolge, in der sie hinzukamen.
knopf.addEventListener("click", () => notiere("erster"));
knopf.addEventListener("click", () => notiere("zweiter"));
knopf.addEventListener("click", () => notiere("dritter"));

// Auch eine direkt hingeschriebene Funktion ist erlaubt.
// Sie hat nur einen Nachteil, und der ist Lektion 12.7.
console.log("Klick den Knopf und sieh dir die Reihenfolge an.");

Du darfst beliebig viele Listener auf dasselbe Element und dasselbe Ereignis legen. Alle laufen, und zwar in der Reihenfolge, in der sie hinzugekommen sind.

Das klingt nach einer Kleinigkeit und ist der Grund, warum addEventListener überhaupt so heißt. Es fügt hinzu, statt zu ersetzen. Verschiedene Teile eines Programms können damit unabhängig voneinander auf dasselbe reagieren, ohne voneinander zu wissen.

Warum kein onclick im Markup

Es gibt einen älteren Weg: <button onclick="melde()"> direkt im HTML. Der funktioniert und kommt in diesem Kurs trotzdem nicht vor.

Er vermischt zwei Dinge. Das Markup beschreibt, was etwas ist, das JavaScript, was es tut. Ein Handler im Attribut steht auf der falschen Seite dieser Trennung, und wer später sucht, wo der Klick behandelt wird, sucht im JavaScript.

Er lässt nur einen zu. Ein zweites onclick überschreibt das erste. Dasselbe gilt für die Eigenschaft el.onclick = ... in JavaScript, die es ebenfalls gibt.

Und er ist genau die Sorte Attribut, die Lektion 11.1 zum Sicherheitsthema gemacht hat. Eine Seite, die ohne Handler in Attributen auskommt, kann ihre Sicherheitseinstellungen strenger fassen.

Zum Mitnehmen

Die Funktion wird übergeben, nicht aufgerufen. Ein Klammerpaar zu viel, und sie läuft sofort einmal und danach nie wieder.

Jetzt du

Basis Konto, kostenlos

Zu dieser Lektion gehört eine Aufgabe. Du schreibst den Code selbst, und nach jedem Lauf sagt dir eine Prüfliste, was schon stimmt.

Dafür brauchst du das Basis Konto. Es kostet nichts, und ein Passwort gibt es auch nicht.

Was in dieser Lektion steckt

  • Artikel mit 3 Beispielen zum Ausprobieren

    Steht hier, ohne Konto lesbar.

  • Aufgabe im Editor, direkt im Browser geprüft

    Öffnet sich mit dem Basis Konto.