event.preventDefault () vs. return false (keine jQuery)

84

Ich fragte mich, ob event.preventDefault()und ob return falsees dasselbe war.

Ich habe einige Tests durchgeführt , und es scheint, dass

  • Wenn der Ereignishandler beispielsweise mit einem alten Modell hinzugefügt wird

    elem.onclick = function(){
        return false;
    };
    

    Dann return falseverhindert Standardaktion, wie event.preventDefault().

  • Wenn der Ereignishandler beispielsweise mit hinzugefügt addEventListenerwird

    elem.addEventListener(
        'click',
        function(e){
            return false;
        },
        false
    );
    

    return falseVerhindert dann nicht die Standardaktion.

Verhalten sich alle Browser so?

Gibt es weitere Unterschiede zwischen event.preventDefault()und return false?

Wo finde ich eine Dokumentation (ich konnte nicht in MDN) über das return falseVerhalten event.preventDefault()in einigen Fällen?


Meine Frage bezieht sich nur auf einfaches Javascript, nicht auf jQuery. Bitte markieren Sie es nicht als Duplikat von event.preventDefault () vs. return false , auch wenn beide Fragen fast den gleichen Titel haben.

Oriol
quelle
Duplikat von stackoverflow.com/questions/1357118/… Wenn Sie die Frage lesen, werden Sie feststellen, dass es sich um ein generisches JS-Problem handelt, nicht um das jQuery-spezifische. jQuery wurde nur verwendet, um den Beispielcode so kurz / sauber wie möglich zu gestalten.
RaYell
13
@ RaYell Nein, da sich jQuery return falseanders verhält als das von einfachem JavaScript. Darüber hinaus hat die andere Frage keine Antwort, die den Unterschied in einfachem JS erklärt (es gibt nur einen Kommentar, der dies erklärt, aber schwer zu finden ist). Ich denke, es ist besser, zwei verschiedene Fragen zu haben.
Oriol

Antworten:

55

Die W3C-Dokumentobjektmodell-Ereignisspezifikation in 1.3.1. Ereignisregistrierungsschnittstellen geben an , dass handleEventim EventListener kein Rückgabewert vorhanden ist:

handleEvent Diese Methode wird immer dann aufgerufen, wenn ein Ereignis des Typs auftritt, für den die EventListener-Schnittstelle registriert wurde. [...] Kein Rückgabewert

unter 1.2.4. Ereignisabbruch Das Dokument gibt auch an, dass

Der Abbruch erfolgt durch Aufrufen der PreventDefault-Methode des Ereignisses. Wenn ein oder mehrere EventListener während einer Phase des Ereignisflusses PreventDefault aufrufen, wird die Standardaktion abgebrochen.

Dies sollte Sie davon abhalten, Effekte zu verwenden, die die Rückgabe von true / false in jedem Browser und in jeder Verwendung haben könnte event.preventDefault().

Aktualisieren

Die HTML5-Spezifikation gibt tatsächlich an, wie ein Rückgabewert anders behandelt werden soll. In Abschnitt 7.1.5.1 der HTML-Spezifikation heißt es:

Wenn der Rückgabewert ein boolescher falscher WebIDL-Wert ist, brechen Sie das Ereignis ab.

für alles außer dem "mouseover" -Ereignis.

Fazit

Ich würde weiterhin empfehlen, event.preventDefault()in den meisten Projekten zu verwenden, da Sie mit der alten Spezifikation und damit älteren Browsern kompatibel sind. Nur wenn Sie nur hochmoderne Browser unterstützen müssen, ist die Rückgabe von false zum Abbrechen in Ordnung.

Thorben Croisé
quelle
2
Dieser Link wurde im Jahr 2000 geschrieben. Die HTML5-Spezifikation: w3.org/TR/html5/webappapis.html#event-handler-attributes sieht so aus, als würde sie Rückgabewerte für viele Ereignisse verarbeiten (kein Mouseover): "Wenn der Rückgabewert ein WebIDL-Boolescher Wert ist falscher Wert, dann das Ereignis abbrechen "
Charles L.
Und von einem schnellen Test in Chrom, sowohl return false und Event.preventDefault () kann nicht Ausbreitung stoppen. Gutschrift hauptsächlich an @Oriol: Siehe Stop Propagation vs. Normal
Charles L.
Diese Geige vergleicht das Verhalten stopPropagation(), preventDefault()und return false: jsfiddle.net/m1L6of9x . In modernen Browsern haben die beiden letzteren das gleiche Verhalten.
Erik Koopmans
4

Hier sind einige Beispiele, die Menschen helfen könnten, ihre Probleme besser zu verstehen und zu beheben.

TL; DR

  • on*Ereignishandler (z. B. onclickAttribut für ein Schaltflächenelement): Geben Sie false zurück, um das Ereignis abzubrechen
  • addEventListenerist 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- getEventListenersAPI 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 clickEreignis 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=functionNamedas 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( !1aufgrund 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 !1aufgrund 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 onclickund addEventListenerin ihren Beispielen verwenden und Folgendes sagen:

Der Verarbeitungsalgorithmus für die Ereignisbehandlungsroutine für eine Ereignisbehandlungsroutine H und ein Ereignisobjekt E lautet wie folgt:

...

  1. 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 falsedas Ereignis für beide storniert addEventListenerund onclick.

Wenn Sie sich jedoch die verknüpfte Definition ansehen, sehen event-handlerSie:

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 falseAbbrechen des Ereignisses nur für die onclick(oder allgemein on*) Ereignishandler gilt und nicht für registrierte Ereignishandler, über addEventListenerdie 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.

mattpr
quelle
-2

Unterschied zwischen präventDefault, stopPropogation, return false

Tabelle mit Unterschied

Standardaktion - Serverseitige Aktion beim Auslösen eines Steuerereignisses.

Angenommen, wir haben Div-Kontrolle und darin haben wir einen Knopf. Div ist also die übergeordnete Steuerung der Schaltfläche. Wir haben Client-Side-Click- und Server-Side-Click-Ereignis der Schaltfläche. Wir haben auch ein clientseitiges Klickereignis des Div.

Beim Klickereignis der Schaltfläche auf der Clientseite können wir die Aktionen der übergeordneten Steuerung und des serverseitigen Codes auf drei Arten steuern:

  • return false- Dies erlaubt nur clientseitige Ereignisse des Steuerelements. Das serverseitige Ereignis und das clientseitige Ereignis des übergeordneten Steuerelements werden nicht ausgelöst.

  • preventDefault()- Dies ermöglicht clientseitige Steuerungsereignisse und deren übergeordnete Steuerung. Serverseitiges Ereignis, dh. Die Standardaktion des Steuerelements wird nicht ausgelöst.

  • stopPropogation()- Dies ermöglicht sowohl clientseitige als auch serverseitige Ereignisse des Steuerelements. Das clientseitige Ereignis des Steuerelements ist nicht zulässig.

Rahul Shinde
quelle
21
Sie liegen falsch, return falsestoppen die Weitergabe nicht, sodass die übergeordnete Steuerung ausgelöst wird ( Demo ). Außerdem bin ich mir nicht sicher, was Sie mit " serverseitigem Klickereignis " meinen .
Oriol
6
@ Anfänger, bitte ignorieren Sie diese Antwort.
Pilau
4
Was ist dieser Unsinn über serverseitige Ereignisse? -1
Mark Amery
Ich denke, das serverseitige Zeug denkt an ASP, wo Sie Ereignisse auf dem Server behandeln lassen können.
Andrew
5
Es gibt keine "serverseitige" Seite, wenn es um JavaScript und Ereignisse geht.
Rawpower
-12

return falseist nur für IE, event.preventDefault()wird von Chrome unterstützt, ff ... moderne Browser

ppy
quelle
9
Aber unter Firefox return falsefunktioniert es so, event.preventDefault()als würde der Event-Handler mit dem alten Modell hinzugefügt
Oriol