Hier sind einige Beispiele, die Menschen helfen könnten, ihre Probleme besser zu verstehen und zu beheben.
TL; DR
on*
Ereignishandler (z. B. onclick
Attribut für ein Schaltflächenelement): Geben Sie false zurück, um das Ereignis abzubrechen
addEventListener
ist eine andere API, Rückgabewerte (zB false
) werden ignoriert: use event.preventDefault()
.
onclick="<somejs>"
hat seine eigene potenzielle Verwirrung, weil <somejs>
es in den Körper einer Onclick-Funktion eingewickelt ist.
- Verwenden Sie die devtools-
getEventListeners
API des Browsers, um zu sehen, wie Ihr Ereignis-Listener zur Fehlerbehebung aussieht, wenn sich Ihr Ereignishandler nicht wie erwartet verhält.
Beispiel
Dieses Beispiel ist spezifisch für das click
Ereignis mit einem <a>
Link ... kann jedoch für die meisten Ereignistypen verallgemeinert werden.
Wir haben einen Anker (Link) mit einer Klasse js-some-link-hook
, mit der wir ein Modal öffnen und verhindern möchten, dass eine Seitennavigation stattfindet.
Die folgenden Beispiele wurden in Google Chrome (71) unter MacOS Mojave ausgeführt.
Eine große Gefahr besteht darin, anzunehmen, dass dies onclick=functionName
das gleiche Verhalten wie bei der Verwendung istaddEventListener
onclick-Attribut
function eventHandler (event) {
// want to prevent link navigation
alert('eventHandler ran');
return false;
}
function addEventListenerToElement () {
var link = document.querySelector('.js-some-link-hook');
link.setAttribute('onclick', eventHandler);
}
addEventListenerToElement();
Führen Sie dann in der Browser-Devtools-Konsole Folgendes aus:
var el = document.querySelector('a.js-some-link-hook'),
listener = getEventListeners(el).click[0].listener;
console.log(''+listener); // to avoid truncation of output
... und du siehst:
function onclick(event) {
function t(n){return alert("eventHandler ran"),!1}
}
Das funktioniert überhaupt nicht. Bei Verwendung onclick=
Ihres Handlers wird die Funktion in eine andere Funktion eingeschlossen. In diesem Fall können Sie sehen, dass meine Funktionsdefinition enthalten ist, aber nicht aufgerufen wird, da ich die Funktionsreferenz angegeben habe, ohne sie aufzurufen. Außerdem können Sie sehen, dass selbst wenn meine Funktion aufgerufen wurde und meine Funktion false zurückgab ... die onclick-Funktion diesen falschen Wert nicht zurückgeben würde ... der erforderlich ist, um das Ereignis abzubrechen. Wir müssen wirklich return myHandlerFunc();
in die Onclick-Funktion eingebunden sein, damit die Dinge funktionieren.
Jetzt, da wir sehen, wie das funktioniert, können wir den Code ändern, um zu tun, was wir wollen. Seltsames Beispiel zur Veranschaulichung (verwenden Sie diesen Code nicht):
function eventHandler (event) {
// want to prevent link navigation
alert('eventHandler ran');
return false;
}
function addEventListenerToElement () {
var link = document.querySelector('.js-some-link-hook');
link.setAttribute('onclick', 'return ('+eventHandler+')();');
}
addEventListenerToElement();
Sie sehen, wir haben unsere eventHandler-Funktionsdefinition in einen String eingeschlossen. Insbesondere: eine selbstausführende Funktion mit einer return-Anweisung an der Vorderseite.
Wieder in der Chrome Devtools-Konsole:
var el = document.querySelector('a.js-some-link-hook'),
listener = getEventListeners(el).click[0].listener;
console.log(''+listener); // to avoid truncation of output
...zeigt an:
function onclick(event) {
return (function t(e){return alert("eventHandler ran"),!1})();
}
... also ja, das sollte funktionieren. Unser return false
( !1
aufgrund minification läuft, sorry). Sicher genug, wenn wir auf den Link klicken, erhalten wir die Warnung und wenn wir die Warnung schließen, navigiert die Seite nirgendwo hin oder wird aktualisiert.
addEventListener
function eventHandler (event) {
// want to prevent link navigation
alert('eventHandler ran');
return false;
}
function addEventListenerToElement () {
var link = document.querySelector('.js-some-link-hook');
link.addEventListener('click', eventHandler, false);
}
addEventListenerToElement();
Browser-Devtools:
var el = document.querySelector('a.js-some-link-hook'),
listener = getEventListeners(el).click[0].listener;
console.log(''+listener); // to avoid truncation of output
Ergebnis:
function e(n){return alert("eventHandler ran"),!1}
So können Sie den Unterschied bereits erkennen. Wir sind nicht in eine Onclick-Funktion eingebunden. Unsere return false
( return !1
aufgrund von Minimierung) ist hier also auf der obersten Ebene und wir müssen uns nicht darum kümmern, wie zuvor eine zusätzliche Rückgabeanweisung hinzuzufügen.
Es sieht also so aus, als ob es funktionieren sollte. Wenn Sie auf den Link klicken, erhalten Sie eine Benachrichtigung. Schließen Sie die Warnung und die Seite navigiert / aktualisiert. dh das Ereignis wurde NICHT durch Rückgabe von false abgebrochen.
Wenn wir die Spezifikation nachschlagen (siehe Ressourcen unten), sehen wir, dass unsere Rückruf- / Handlerfunktion für addEventListener keinen Rückgabetyp unterstützt. Wir können zurückgeben, was wir wollen, aber da es nicht Teil der Benutzeroberfläche ist, hat es keine Auswirkungen.
Lösung: Verwenden event.preventDefault()
statt return false;
...
function eventHandler (event) {
// want to prevent link navigation
event.preventDefault();
alert('eventHandler ran');
}
function addEventListenerToElement () {
var link = document.querySelector('.js-some-link-hook');
link.addEventListener('click', eventHandler, false);
}
addEventListenerToElement();
Browser Devtools ...
var el = document.querySelector('a.js-some-link-hook'),
listener = getEventListeners(el).click[0].listener;
console.log(''+listener); // to avoid truncation of output
gibt ...
function n(e){e.preventDefault(),alert("eventHandler ran")}
...wie erwartet.
Testen: Alarm erhalten. Alarm abweisen. Keine Seitennavigation oder Aktualisierung ... was wir wollen.
Ressourcen
Die HTML5-Spezifikation ( https://www.w3.org/TR/html5/webappapis.html#events ) verwirrt die Dinge, weil sie beide onclick
und addEventListener
in ihren Beispielen verwenden und Folgendes sagen:
Der Verarbeitungsalgorithmus für die Ereignisbehandlungsroutine für eine Ereignisbehandlungsroutine H und ein Ereignisobjekt E lautet wie folgt:
...
- Verarbeiten Sie den Rückgabewert wie folgt:
...
Wenn der Rückgabewert ein boolescher falscher Web IDL-Wert ist, brechen Sie das Ereignis ab.
So scheint es zu bedeuten , dass return false
das Ereignis für beide storniert addEventListener
und onclick
.
Wenn Sie sich jedoch die verknüpfte Definition ansehen, sehen event-handler
Sie:
Ein Ereignishandler hat einen Namen, der immer mit "Ein" beginnt, gefolgt vom Namen des Ereignisses, für das er bestimmt ist.
...
Ereignishandler werden auf zwei Arten verfügbar gemacht.
Der erste Weg, der allen Ereignishandlern gemeinsam ist, ist das IDL-Attribut des Ereignishandlers.
Der zweite Weg ist ein Inhaltsattribut für die Ereignisbehandlungsroutine. Ereignishandler für HTML-Elemente und einige der Ereignishandler für Fensterobjekte werden auf diese Weise verfügbar gemacht.
https://www.w3.org/TR/html5/webappapis.html#event-handler
Es scheint also, dass das return false
Abbrechen des Ereignisses nur für die onclick
(oder allgemein on*
) Ereignishandler gilt und nicht für registrierte Ereignishandler, über addEventListener
die eine andere API verfügt. Da die addEventListener-API nicht unter die HTML5-Spezifikation und nur die on*
Ereignishandler fällt , wäre es weniger verwirrend, wenn sie sich in ihren Beispielen daran halten und den Unterschied ausdrücklich herausstellen würden.