Einführung in Ereignisse
Ereignisse sind Dinge, die im System, das Sie programmieren, geschehen und über die das System Sie informiert, damit Ihr Code darauf reagieren kann.
Zum Beispiel, wenn der Benutzer auf einen Knopf auf einer Webseite klickt, möchten Sie möglicherweise auf diese Aktion reagieren, indem Sie ein Informationsfenster anzeigen. In diesem Artikel besprechen wir einige wichtige Konzepte rund um Ereignisse und betrachten, wie sie in Browsern funktionieren. Dies wird keine umfassende Studie sein, sondern nur das, was Sie in diesem Stadium wissen müssen.
Voraussetzungen: | Ein grundlegendes Verständnis von HTML, CSS und Erste Schritte in JavaScript. |
---|---|
Ziel: | Das grundlegende Konzept von Ereignissen zu verstehen, wie sie in Browsern funktionieren und wie Ereignisse sich in verschiedenen Programmierumgebungen unterscheiden können. |
Was ist ein Ereignis?
Ereignisse sind Dinge, die im System, das Sie programmieren, geschehen — das System erzeugt (oder "feuert") ein Signal irgendeiner Art, wenn ein Ereignis auftritt, und bietet einen Mechanismus, durch den eine Aktion automatisch ausgeführt werden kann (das heißt, ein Code, der ausgeführt wird), wenn das Ereignis auftritt. Ereignisse werden innerhalb des Browserfensters ausgelöst und tendieren dazu, an ein spezifisches Element gebunden zu sein, das sich darin befindet. Dies könnte ein einzelnes Element, eine Gruppe von Elementen, das HTML-Dokument, das im aktuellen Tab geladen ist, oder das gesamte Browserfenster sein. Es gibt viele verschiedene Arten von Ereignissen, die auftreten können.
Zum Beispiel:
- Der Benutzer wählt, klickt oder schwebt mit dem Cursor über ein bestimmtes Element.
- Der Benutzer wählt eine Taste auf der Tastatur.
- Der Benutzer ändert die Größe oder schließt das Browserfenster.
- Eine Webseite wird fertig geladen.
- Ein Formular wird abgeschickt.
- Ein Video wird abgespielt, pausiert oder endet.
- Ein Fehler tritt auf.
Daraus (und aus einem Blick auf die MDN Ereignisreferenz) können Sie entnehmen, dass es viele Ereignisse gibt, die ausgelöst werden können.
Um auf ein Ereignis zu reagieren, befestigen Sie einen Ereignishandler daran. Dies ist ein Block von Code (normalerweise eine von Ihnen als Programmierer erstellte JavaScript-Funktion), die ausgeführt wird, wenn das Ereignis ausgelöst wird. Wenn ein solcher Codeblock definiert ist, um als Reaktion auf ein Ereignis ausgeführt zu werden, sagen wir, dass wir einen Ereignishandler registrieren. Hinweis: Ereignishandler werden manchmal auch Ereignislistener genannt — sie sind für unsere Zwecke ziemlich austauschbar, obwohl sie streng genommen zusammenarbeiten. Der Listener hört auf das Auftreten des Ereignisses, und der Handler ist der Code, der als Reaktion darauf ausgeführt wird.
Hinweis: Web-Ereignisse sind nicht Teil der grundlegenden JavaScript-Sprache — sie sind Teil der in den Browser integrierten APIs definiert.
Ein Beispiel: Ein Klickevent behandeln
Im folgenden Beispiel haben wir ein einzelnes <button>
auf der Seite:
<button>Change color</button>
Dann haben wir etwas JavaScript. Wir werden dies im nächsten Abschnitt detaillierter betrachten, aber vorerst können wir nur sagen: es fügt dem "click"
-Ereignis des Knopfes einen Ereignishandler hinzu, und der Handler reagiert auf das Ereignis, indem er den Hintergrund der Seite auf eine zufällige Farbe ändert:
const btn = document.querySelector("button");
function random(number) {
return Math.floor(Math.random() * (number + 1));
}
btn.addEventListener("click", () => {
const rndCol = `rgb(${random(255)} ${random(255)} ${random(255)})`;
document.body.style.backgroundColor = rndCol;
});
Das Beispielausgabe ist wie folgt. Versuchen Sie, den Knopf zu klicken:
Verwendung von addEventListener()
Wie wir im letzten Beispiel gesehen haben, haben Objekte, die Ereignisse auslösen können, eine addEventListener()
-Methode, und dies ist der empfohlene Mechanismus zum Hinzufügen von Ereignishandlern.
Lassen Sie uns den Code aus dem letzten Beispiel genauer betrachten:
const btn = document.querySelector("button");
function random(number) {
return Math.floor(Math.random() * (number + 1));
}
btn.addEventListener("click", () => {
const rndCol = `rgb(${random(255)} ${random(255)} ${random(255)})`;
document.body.style.backgroundColor = rndCol;
});
Das HTML <button>
-Element wird ein Ereignis auslösen, wenn der Benutzer auf den Knopf klickt. Also definiert es eine addEventListener()
-Funktion, die wir hier aufrufen. Wir übergeben zwei Parameter:
- den String
"click"
, um anzuzeigen, dass wir dem Klickereignis zuhören möchten. Schaltflächen können viele andere Ereignisse auslösen, wie"mouseover"
, wenn der Benutzer mit der Maus über die Schaltfläche fährt, oder"keydown"
, wenn der Benutzer eine Taste drückt und die Schaltfläche fokussiert ist. - eine Funktion, die aufgerufen werden soll, wenn das Ereignis passiert. In unserem Fall erzeugt die Funktion eine zufällige RGB-Farbe und setzt die
background-color
der Seite<body>
auf diese Farbe.
Es ist in Ordnung, die Handlerfunktion zu einer separaten benannten Funktion zu machen, wie hier:
const btn = document.querySelector("button");
function random(number) {
return Math.floor(Math.random() * (number + 1));
}
function changeBackground() {
const rndCol = `rgb(${random(255)} ${random(255)} ${random(255)})`;
document.body.style.backgroundColor = rndCol;
}
btn.addEventListener("click", changeBackground);
Zuhören auf andere Ereignisse
Es gibt viele verschiedene Ereignisse, die von einem Schalterein Element ausgelöst werden können. Lassen Sie uns experimentieren.
Erstellen Sie zunächst eine lokale Kopie von random-color-addeventlistener.html und öffnen Sie sie in Ihrem Browser. Es ist nur eine Kopie des einfachen Zufallsfarbenbeispiels, mit dem wir bereits gespielt haben. Versuchen Sie nun, click
in die folgenden unterschiedlichen Werte zu ändern und beobachten Sie die Ergebnisse im Beispiel:
focus
undblur
— Die Farbe ändert sich, wenn die Schaltfläche fokussiert und entfokussiert wird; versuchen Sie, die Tab-Taste zu drücken, um die Schaltfläche zu fokussieren, und drücken Sie die Tab-Taste erneut, um den Fokus von der Schaltfläche zu entfernen. Diese werden oft verwendet, um Informationen zur Ausfüllung von Formularfeldern anzuzeigen, wenn diese fokussiert sind, oder um eine Fehlermeldung anzuzeigen, wenn ein Formularfeld mit einem falschen Wert ausgefüllt wird.dblclick
— Die Farbe ändert sich nur, wenn die Schaltfläche doppelt geklickt wird.mouseover
undmouseout
— Die Farbe ändert sich, wenn der Mauszeiger über die Schaltfläche schwebt oder wenn der Zeiger von der Schaltfläche weg bewegt wird.
Einige Ereignisse, wie click
, stehen bei fast jedem Element zur Verfügung. Andere sind spezifischer und nur in bestimmten Situationen nützlich: zum Beispiel ist das play
-Ereignis nur bei einigen Elementen verfügbar, wie etwa <video>
.
Entfernen von Listenern
Wenn Sie einen Ereignishandler mit addEventListener()
hinzugefügt haben, können Sie ihn wieder entfernen, indem Sie die Methode removeEventListener()
verwenden. Zum Beispiel würde dies den changeBackground()
-Ereignishandler entfernen:
btn.removeEventListener("click", changeBackground);
Ereignishandler können auch entfernt werden, indem ein AbortSignal
an addEventListener()
übergeben wird und dann später abort()
auf dem Controller aufgerufen wird, der das AbortSignal
besitzt. Zum Beispiel, um einen Ereignishandler hinzuzufügen, den wir mit einem AbortSignal
entfernen können:
const controller = new AbortController();
btn.addEventListener("click",
() => {
const rndCol = `rgb(${random(255)} ${random(255)} ${random(255)})`;
document.body.style.backgroundColor = rndCol;
},
{ signal: controller.signal } // pass an AbortSignal to this handler
);
Der durch den obigen Code erstellte Ereignishandler kann dann wie folgt entfernt werden:
controller.abort(); // removes any/all event handlers associated with this controller
Für einfache, kleine Programme ist das Bereinigen alter, ungenutzter Ereignishandler nicht notwendig, aber bei größeren, komplexeren Programmen kann dies die Effizienz verbessern. Auch ermöglicht das Entfernen von Ereignishandlern, dass dieselbe Schaltfläche unter verschiedenen Umständen unterschiedliche Aktionen ausführt: Sie müssen lediglich Handler hinzufügen oder entfernen.
Hinzufügen mehrerer Listener für ein einzelnes Ereignis
Durch mehrmaliges Aufrufen von addEventListener()
mit unterschiedlichen Handlern können Sie mehrere Handler für ein einzelnes Ereignis haben:
myElement.addEventListener("click", functionA);
myElement.addEventListener("click", functionB);
Beide Funktionen würden jetzt ausgeführt werden, wenn das Element angeklickt wird.
Erfahren Sie mehr
Es gibt weitere leistungsstarke Funktionen und Optionen mit addEventListener()
.
Diese sind ein wenig außerhalb des Umfangs dieses Artikels, aber wenn Sie mehr darüber erfahren möchten, besuchen Sie die Referenzseiten zu addEventListener()
und removeEventListener()
.
Andere Mechanismen für Ereignislistener
Wir empfehlen, dass Sie addEventListener()
verwenden, um Ereignishandler zu registrieren. Es ist die leistungsstärkste Methode und skaliert am besten mit komplexeren Programmen. Es gibt jedoch zwei weitere Möglichkeiten zum Registrieren von Ereignishandlern, die Sie möglicherweise sehen: Ereignishandler-Eigenschaften und Inline-Ereignishandler.
Ereignishandler-Eigenschaften
Objekte (wie Knöpfe), die Ereignisse auslösen können, haben in der Regel auch Eigenschaften, deren Name mit on
gefolgt von dem Namen des Ereignisses beginnt. Zum Beispiel haben Elemente eine onclick
-Eigenschaft. Dies wird als Ereignishandler-Eigenschaft bezeichnet. Um auf das Ereignis zu hören, können Sie die Handlerfunktion auf die Eigenschaft zuweisen.
Zum Beispiel könnten wir das Zufallsfarben-Beispiel so umschreiben:
const btn = document.querySelector("button");
function random(number) {
return Math.floor(Math.random() * (number + 1));
}
btn.onclick = () => {
const rndCol = `rgb(${random(255)} ${random(255)} ${random(255)})`;
document.body.style.backgroundColor = rndCol;
};
Sie können die Handler-Eigenschaft auch auf eine benannte Funktion setzen:
const btn = document.querySelector("button");
function random(number) {
return Math.floor(Math.random() * (number + 1));
}
function bgChange() {
const rndCol = `rgb(${random(255)} ${random(255)} ${random(255)})`;
document.body.style.backgroundColor = rndCol;
}
btn.onclick = bgChange;
Mit Ereignishandler-Eigenschaften können Sie nicht mehr als einen Handler für ein einzelnes Ereignis hinzufügen. Zum Beispiel können Sie addEventListener('click', handler)
bei einem Element mehrfach aufrufen, mit verschiedenen Funktionen, die im zweiten Argument angegeben sind:
element.addEventListener("click", function1);
element.addEventListener("click", function2);
Dies ist unmöglich mit Ereignishandler-Eigenschaften, da alle nachfolgenden Versuche, die Eigenschaft zu setzen, frühere überschreiben werden:
element.onclick = function1;
element.onclick = function2;
Inline-Ereignishandler — verwenden Sie diese nicht
Sie könnten auch ein Muster wie dieses in Ihrem Code sehen:
<button onclick="bgChange()">Press me</button>
function bgChange() {
const rndCol = `rgb(${random(255)} ${random(255)} ${random(255)})`;
document.body.style.backgroundColor = rndCol;
}
Die früheste Methode zum Registrieren von Ereignishandlern, die im Web gefunden wurde, beinhaltete Ereignishandler-HTML-Attribute (oder Inline-Ereignishandler) wie das obige — der Attributwert ist buchstäblich der JavaScript-Code, den Sie ausführen möchten, wenn das Ereignis auftritt. Das obige Beispiel ruft eine Funktion auf, die innerhalb eines <script>
-Elements auf derselben Seite definiert ist, aber Sie könnten auch JavaScript direkt im Attribut einfügen, zum Beispiel:
<button onclick="alert('Hello, this is my old-fashioned event handler!');">
Press me
</button>
Sie finden HTML-Attribut-Pendants zu vielen der Ereignishandler-Eigenschaften; jedoch sollten Sie diese nicht verwenden — sie gelten als schlechte Praxis. Es mag einfach erscheinen, ein Ereignishandler-Attribut zu verwenden, wenn Sie etwas sehr Schnelles tun, aber sie werden schnell unhandlich und ineffizient.
Zum einen ist es keine gute Idee, Ihr HTML und Ihr JavaScript zu vermischen, da es schwer zu lesen wird. Es ist eine gute Praxis, Ihr JavaScript getrennt zu halten, und wenn es sich in einer separaten Datei befindet, können Sie es auf mehrere HTML-Dokumente anwenden.
Selbst in einer einzigen Datei sind Inline-Ereignishandler keine gute Idee. Ein Knopf ist in Ordnung, aber was wäre, wenn Sie 100 Knöpfe hätten? Sie müssten 100 Attribute in die Datei einfügen, es würde schnell zu einem Wartungsalbtraum werden. Mit JavaScript könnten Sie leicht eine Ereignishandler-Funktion zu allen Schaltflächen auf der Seite hinzufügen, egal wie viele es gibt, mit etwas wie diesem:
const buttons = document.querySelectorAll("button");
for (const button of buttons) {
button.addEventListener("click", bgChange);
}
Schließlich werden viele gängige Serverkonfigurationen Inline-JavaScript als Sicherheitsmaßnahme verbieten.
Sie sollten niemals die HTML-Ereignishandler-Attribute verwenden — diese sind veraltet, und ihre Verwendung ist schlechte Praxis.
Ereignisobjekte
Manchmal sehen Sie in einer Ereignishandlerfunktion einen angegebenen Parameter mit einem Namen wie event
, evt
oder e
. Dies wird das Ereignisobjekt genannt und automatisch an Ereignishandler übergeben, um zusätzliche Funktionen und Informationen bereitzustellen. Zum Beispiel, lassen Sie uns unser Zufallsfarben-Beispiel erneut etwas umschreiben:
const btn = document.querySelector("button");
function random(number) {
return Math.floor(Math.random() * (number + 1));
}
function bgChange(e) {
const rndCol = `rgb(${random(255)} ${random(255)} ${random(255)})`;
e.target.style.backgroundColor = rndCol;
console.log(e);
}
btn.addEventListener("click", bgChange);
Hinweis: Sie können den vollen Quellcode für dieses Beispiel auf GitHub finden (sehen Sie es auch live laufen).
Hier sehen Sie, dass wir ein Ereignisobjekt, e, in der Funktion einschließen und in der Funktion einen Hintergrundfarbstil auf e.target
setzen — das ist der Button selbst. Die target
-Eigenschaft des Ereignisobjekts ist immer ein Verweis auf das Element, auf dem das Ereignis aufgetreten ist. In diesem Beispiel setzen wir also eine zufällige Hintergrundfarbe auf den Button, nicht auf die Seite.
Hinweis: Sie können jeden beliebigen Namen für das Ereignisobjekt verwenden — Sie müssen nur einen Namen wählen, den Sie dann verwenden können, um es innerhalb der Ereignishandlerfunktion zu referenzieren. e
/evt
/event
wird am häufigsten von Entwicklern verwendet, da sie kurz und leicht zu merken sind. Es ist immer gut, konsistent zu sein — mit sich selbst und, wenn möglich, mit anderen.
Zusätzliche Eigenschaften von Ereignisobjekten
Die meisten Ereignisobjekte haben eine Standardsammlung von Eigenschaften und Methoden, die auf dem Ereignisobjekt verfügbar sind; siehe die Event
Objektreferenz für eine vollständige Liste.
Einige Ereignisobjekte fügen zusätzliche Eigenschaften hinzu, die für diesen bestimmten Ereignistyp relevant sind. Zum Beispiel wird das keydown
-Ereignis ausgelöst, wenn der Benutzer eine Taste drückt. Sein Ereignisobjekt ist ein KeyboardEvent
, das ein spezialisiertes Event
-Objekt mit einer key
-Eigenschaft ist, die angibt, welche Taste gedrückt wurde:
<input id="textBox" type="text" />
<div id="output"></div>
const textBox = document.querySelector("#textBox");
const output = document.querySelector("#output");
textBox.addEventListener("keydown", (event) => {
output.textContent = `You pressed "${event.key}".`;
});
Versuchen Sie, in das Textfeld zu tippen, und sehen Sie die Ausgabe:
Standardverhalten verhindern
Manchmal stoßen Sie auf eine Situation, in der Sie verhindern möchten, dass ein Ereignis das tut, was es standardmäßig tut. Das häufigste Beispiel ist das eines Webformulars, zum Beispiel eines benutzerdefinierten Registrierungsformulars. Wenn Sie die Daten ausfüllen und die Absende-Schaltfläche klicken, ist das natürliche Verhalten, dass die Daten an eine angegebene Seite auf dem Server zur Verarbeitung gesendet werden, und der Browser wird zu einer Art "Erfolgsmeldung"-Seite umgeleitet (oder zur gleichen Seite, wenn keine andere angegeben ist).
Das Problem entsteht, wenn der Benutzer die Daten nicht korrekt übermittelt hat — als Entwickler möchten Sie verhindern, dass die Übermittlung an den Server erfolgt und eine Fehlermeldung anzeigen, die angibt, was falsch ist und was getan werden muss, um es richtig zu stellen. Einige Browser unterstützen automatische Validierungsfunktionen für Formulardaten, aber da viele das nicht tun, sollten Sie sich nicht darauf verlassen und Ihre eigenen Validierungsprüfungen implementieren. Lassen Sie uns ein Beispiel betrachten.
Zuerst ein einfaches HTML-Formular, das erfordert, dass Sie Ihren Vor- und Nachnamen eingeben:
<form>
<div>
<label for="fname">First name: </label>
<input id="fname" type="text" />
</div>
<div>
<label for="lname">Last name: </label>
<input id="lname" type="text" />
</div>
<div>
<input id="submit" type="submit" />
</div>
</form>
<p></p>
Nun etwas JavaScript — hier implementieren wir eine sehr einfache Prüfung innerhalb eines Handlers für das submit
-Ereignis (das Submit-Ereignis wird auf einem Formular ausgelöst, wenn es übermittelt wird), die prüft, ob die Textfelder leer sind. Wenn sie es sind, rufen wir die Funktion preventDefault()
auf dem Ereignisobjekt auf — was die Formularübermittlung stoppt — und zeigen dann eine Fehlermeldung im Absatz unter unserem Formular an, um dem Benutzer zu sagen, was falsch ist:
const form = document.querySelector("form");
const fname = document.getElementById("fname");
const lname = document.getElementById("lname");
const para = document.querySelector("p");
form.addEventListener("submit", (e) => {
if (fname.value === "" || lname.value === "") {
e.preventDefault();
para.textContent = "You need to fill in both names!";
}
});
Natürlich ist dies eine ziemlich schwache Formularvalidierung — sie würde nicht verhindern, dass der Benutzer das Formular mit Leerzeichen oder Zahlen in den Feldern validiert — aber es ist in Ordnung für Beispielzwecke. Die Ausgabe ist wie folgt:
Hinweis: Für den vollständigen Quellcode, siehe preventdefault-validation.html (sehen Sie es auch live laufen hier).
Es sind nicht nur Webseiten
Ereignisse sind nicht einzigartig für JavaScript — die meisten Programmiersprachen haben irgendeine Art von Ereignismodell, und die Funktionsweise des Modells unterscheidet sich oft von der in JavaScript. Tatsächlich unterscheidet sich das Ereignismodell in JavaScript für Webseiten vom Ereignismodell für JavaScript, wie es in anderen Umgebungen verwendet wird.
Zum Beispiel ist Node.js eine sehr beliebte JavaScript-Laufzeit, die es Entwicklern ermöglicht, JavaScript zur Erstellung von Netzwerk- und serverseitigen Anwendungen zu verwenden. Das Node.js-Ereignismodell basiert auf Listenern, die auf Ereignisse hören, und Emittenten, die regelmäßig Ereignisse auslösen — es klingt nicht so anders, aber der Code ist ziemlich unterschiedlich, indem Funktionen wie on()
verwendet werden, um einen Ereignislistener zu registrieren und once()
, um einen Ereignislistener zu registrieren, der sich entfernt, nachdem er einmal ausgeführt wurde. Die HTTP-Connect-Event-Dokumentation bietet ein gutes Beispiel.
Sie können JavaScript auch verwenden, um plattformübergreifende Add-Ons zu erstellen — Erweiterungen der Browserfunktionen — mit einer Technologie namens WebExtensions. Das Ereignismodell ist ähnlich wie das Web-Ereignismodell, aber etwas anders — Eigenschaftennamen von Ereignislistenern werden im Camel Case geschrieben (wie onMessage
statt onmessage
), und müssen mit der addListener
-Funktion kombiniert werden. Siehe die Seite runtime.onMessage
für ein Beispiel.
Sie müssen in dieser Phase Ihres Lernens nichts über andere solche Umgebungen verstehen; wir wollten nur klarstellen, dass sich Ereignisse in verschiedenen Programmierumgebungen unterscheiden können.
Fazit
In diesem Kapitel haben wir gelernt, was Ereignisse sind, wie man auf Ereignisse lauschen kann und wie man auf sie reagieren kann.
Sie haben bis jetzt gesehen, dass Elemente in einer Webseite in andere Elemente verschachtelt werden können. Zum Beispiel haben wir im Verhindern des Standardverhaltens-Beispiel einige Textfelder, die in <div>
-Elementen untergebracht sind, die wiederum in einem <form>
-Element platziert sind. Was passiert, wenn ein Klickereignis-Listener an das <form>
-Element befestigt ist und der Benutzer in eines der Textfelder klickt? Dies wird als Ereignis-Bubbling bezeichnet und ist das Thema des nächsten Kapitels.