Was ist der Unterschied zwischen event.stopPropagation und event.preventDefault?

833

Sie scheinen dasselbe zu tun ...
Ist einer modern und einer alt? Oder werden sie von verschiedenen Browsern unterstützt?

Wenn ich Ereignisse selbst (ohne Framework) behandle, überprüfe ich einfach immer beide und führe beide aus, falls vorhanden. (Ich auch return false, aber ich habe das Gefühl, dass es mit Ereignissen, die damit verbunden sind, nicht funktioniert node.addEventListener).

Warum also beide? Soll ich weiter nach beidem suchen? Oder gibt es tatsächlich einen Unterschied?

(Ich weiß, viele Fragen, aber sie sind alle gleich =))

Rudie
quelle

Antworten:

1014

stopPropagation verhindert, dass das Ereignis die Ereigniskette in die Luft sprudelt.

preventDefault verhindert die Standardaktion, die der Browser für dieses Ereignis ausführt.

Beispiele

Standard verhindern

$("#but").click(function (event) {
  event.preventDefault()
})
$("#foo").click(function () {
  alert("parent click event fired!")
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="foo">
  <button id="but">button</button>
</div>

stopPropagation

$("#but").click(function (event) {
  event.stopPropagation()
})
$("#foo").click(function () {
  alert("parent click event fired!")
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="foo">
  <button id="but">button</button>
</div>

Mit stopPropagationwird nur der buttonKlick-Handler des Klicks aufgerufen, während der divKlick-Handler des Klicks niemals ausgelöst wird.

Wo, als ob Sie verwenden preventDefault, wird nur die Standardaktion des Browsers gestoppt, aber der Klick-Handler des Div wird weiterhin ausgelöst.

Im Folgenden finden Sie einige Dokumente zu den DOM-Ereigniseigenschaften und -methoden von MDN:

Für IE9 und FF können Sie einfach präventDefault & stopPropagation verwenden.

Zur Unterstützung von IE8 und senken ersetzen stopPropagationmit cancelBubbleund ersetzen preventDefaultmitreturnValue

Raynos
quelle
Also sind sie sehr unterschiedlich? Hat der IE auch dafür zwei verschiedene Ereignismethoden? (Könnten sie gleich sein?) Es ist seltsam, dass Frameworks beides in ihrer event.stopFunktion tun ... Auch seltsam, dass ich damit nie Probleme hatte. Ich benutze viel Sprudeln. Danke für das Beispiel!
Rudie
@ Rudie kommentierte die Browserunterstützung.
Raynos
7
Es ist erwähnenswert (falls Sie sich die MSDN-Dokumente nicht ansehen), dass cancelBubbleund returnValuebeide Eigenschaften sind (also festgelegt werden sollten cancelBubble = true;) und dass preventDefaultund stopPropagationMethoden sind (so genannt werden sollten preventDefault();)
freefaller
1
@Raynos, nur eine Anmerkung: event.stopPropagation () verhindert nicht nur, dass das Ereignis die Ereigniskette in die Luft sprudelt, sondern auch die Ereignisausbreitung in der Erfassungsphase ( developer.mozilla.org/en-US/docs/Web/). API / Event / stopPropagation )
Yuci
1
Es wäre hilfreich zu wissen, was die Standardaktion für einen Klick auf eine Schaltfläche ist, damit ich darüber nachdenken kann, warum stopDefault()dies nicht genauso funktioniert wie stopPropagation(). Wenn die Standardaktion die onclickMethode nicht aufruft , was ist das?
d512
249

Terminologie

Von quirksmode.org :

Ereigniserfassung

Wenn Sie die Ereigniserfassung verwenden

               | |
--------------- | | -----------------
| element1 | | |
| ----------- | | ----------- |
| | element2 \ / | |
| ------------------------- |
| Ereignis ERFASSUNG |
-----------------------------------

Der Ereignishandler von Element1 wird zuerst ausgelöst, der Ereignishandler von Element2 wird zuletzt ausgelöst.

Ereignis sprudelt

Wenn Sie Ereignisblasen verwenden

               / \.
--------------- | | -----------------
| element1 | | |
| ----------- | | ----------- |
| | element2 | | | |
| ------------------------- |
| Ereignis BUBBLING |
-----------------------------------

Der Ereignishandler von Element2 wird zuerst ausgelöst, der Ereignishandler von Element1 wird zuletzt ausgelöst.

Jedes Ereignis, das im W3C-Ereignismodell stattfindet, wird zuerst erfasst, bis es das Zielelement erreicht, und sprudelt dann wieder hoch .

                 | | / \.
----------------- | | - | | -----------------
| element1 | | | | |
| ------------- | | - | | ----------- |
| | element2 \ / | | | |
| -------------------------------- |
| W3C-Ereignismodell |
--------------------------------------

Schnittstelle

Von w3.org zur Ereigniserfassung :

Wenn die Erfassung EventListenerverhindern soll, dass das Ereignis weiter verarbeitet wird, kann sie die stopPropagationMethode der EventSchnittstelle aufrufen . Dies verhindert einen weiteren Versand des Ereignisses, obwohl zusätzliche, EventListenersdie auf derselben Hierarchieebene registriert sind, das Ereignis weiterhin erhalten. Sobald die stopPropagation Methode eines Ereignisses aufgerufen wurde, haben weitere Aufrufe dieser Methode keine zusätzlichen Auswirkungen. Wenn keine zusätzlichen Capturer vorhanden sind und stopPropagationnicht aufgerufen wurden, löst das Ereignis das entsprechende EventListenersauf dem Ziel selbst aus.

Für sprudelnde Ereignisse :

Jeder Ereignishandler kann eine weitere Ereignisausbreitung verhindern, indem er die stopPropagationMethode der EventSchnittstelle aufruft . Wenn jemand EventListenerdiese Methode aufruft, werden alle zusätzlichen EventListenersDaten des Stroms EventTargetausgelöst, aber das Sprudeln hört auf dieser Ebene auf. Es ist nur ein Anruf stopPropagationerforderlich, um ein weiteres Sprudeln zu verhindern.

Für die Absage von Veranstaltungen :

Cancelation wird erreicht , indem der Aufruf Events‘ preventDefault Methode. Wenn ein oder mehrere EventListenersAnrufe preventDefaultwährend einer Phase des Ereignisflusses getätigt werden, wird die Standardaktion abgebrochen.

Beispiele

In den folgenden Beispielen löst ein Klick auf den Hyperlink im Webbrowser den Ereignisfluss (die Ereignis-Listener werden ausgeführt) und die Standardaktion des Ereignisziels aus (eine neue Registerkarte wird geöffnet).

HTML:

<div id="a">
  <a id="b" href="http://www.google.com/" target="_blank">Google</a>
</div>
<p id="c"></p>

JavaScript:

var el = document.getElementById("c");

function capturingOnClick1(ev) {
    el.innerHTML += "DIV event capture<br>";
}

function capturingOnClick2(ev) {
    el.innerHTML += "A event capture<br>";
}

function bubblingOnClick1(ev) {
    el.innerHTML += "DIV event bubbling<br>";
}

function bubblingOnClick2(ev) {
    el.innerHTML += "A event bubbling<br>";
}

// The 3rd parameter useCapture makes the event listener capturing (false by default)
document.getElementById("a").addEventListener("click", capturingOnClick1, true);
document.getElementById("b").addEventListener("click", capturingOnClick2, true);
document.getElementById("a").addEventListener("click", bubblingOnClick1, false);
document.getElementById("b").addEventListener("click", bubblingOnClick2, false);

Beispiel 1 : Es ergibt sich die Ausgabe

DIV event capture
A event capture
A event bubbling
DIV event bubbling

Beispiel 2 : Hinzufügen stopPropagation()zur Funktion

function capturingOnClick1(ev) {
    el.innerHTML += "DIV event capture<br>";
    ev.stopPropagation();
}

führt zur Ausgabe

DIV event capture

Der Ereignis-Listener verhinderte eine weitere Ausbreitung des Ereignisses nach unten und oben. Die Standardaktion (das Öffnen einer neuen Registerkarte) wurde jedoch nicht verhindert.

Beispiel 3 : Hinzufügen stopPropagation()zur Funktion

function capturingOnClick2(ev) {
    el.innerHTML += "A event capture<br>";
    ev.stopPropagation();
}

oder die Funktion

function bubblingOnClick2(ev) {
    el.innerHTML += "A event bubbling<br>";
    ev.stopPropagation();
}

führt zur Ausgabe

DIV event capture
A event capture
A event bubbling

Dies liegt daran, dass beide Ereignis-Listener auf demselben Ereignisziel registriert sind. Die Ereignis-Listener verhinderten eine weitere Ausbreitung des Ereignisses nach oben. Sie haben jedoch die Standardaktion (das Öffnen einer neuen Registerkarte) nicht verhindert.

Beispiel 4 : preventDefault()Zum Beispiel zu einer beliebigen Funktion hinzufügen

function capturingOnClick1(ev) {
    el.innerHTML += "DIV event capture<br>";
    ev.preventDefault();
}

verhindert, dass sich eine neue Registerkarte öffnet.

Ashkan
quelle
23
Vielen Dank für die tiefere Unterscheidung zwischen Erfassen und Sprudeln, während die andere Antwort nur die Bedenken von jQuery anspricht.
Floribon
@floribon sagen, Sie haben nicht die Absicht, Raynos für seine Antwort zu beleidigen.
Mahi
3
@ Mahi was? Ich sage nur Fakten, die akzeptierte Antwort verwendet jQuery, was von OP nicht angenommen wird. Für mich ist es also nicht die eigentliche Antwort. Das ist nur eine technische Tatsache, nichts Persönliches und niemand, der beleidigt werden kann.
Floribon
2
Ihre Antwort ist sehr systematisch und zeigt deutlich, was los ist. Anfangs wollte ich Sie nicht stören und selbst einige Änderungen an Ihrer Antwort vornehmen, da ich denke, dass sie aus Gründen der Klarheit ein wenig verbessert werden könnte. Diese Antwort erklärt Anfängern das Veranstaltungsmodell und daher denke ich, dass jede Hilfe, die wir Anfängern geben können, einen langen Weg geht. Mein Bearbeitungsvorschlag wurde durch allgemeine Argumente abgelehnt , mit denen ich nicht einverstanden bin. Wenn Sie, @Ashkan, der Meinung sind, dass diese kleinen Änderungen zur Verbesserung der Antwort beitragen könnten, nehmen Sie sie bitte auf.
Mucaho
68

falsch zurückgeben;


return false; macht 3 verschiedene Dinge, wenn Sie es nennen:

  1. event.preventDefault() - Es stoppt das Standardverhalten des Browsers.
  2. event.stopPropagation() - Es verhindert, dass das Ereignis das DOM verbreitet (oder "sprudelt").
  3. Stoppt die Rückrufausführung und kehrt beim Aufruf sofort zurück.

Beachten Sie, dass sich dieses Verhalten von normalen (Nicht-jQuery-) Ereignishandlern unterscheidet, bei denen insbesondere return falsedas Sprudeln des Ereignisses nicht verhindert wird.

Standard verhindern();


preventDefault(); macht eine Sache: Es stoppt das Standardverhalten des Browsers.

Wann man sie benutzt?


Wir wissen, was sie tun, aber wann sie zu verwenden sind? Es kommt einfach darauf an, was Sie erreichen wollen. Verwenden preventDefault();Sie diese Option, wenn Sie das Standardverhalten des Browsers "nur" verhindern möchten. Verwenden Sie return false. wenn Sie das Standardverhalten des Browsers verhindern und verhindern möchten, dass das Ereignis das DOM weitergibt. In den meisten Situationen, in denen Sie return false verwenden würden; was du wirklich willst ist preventDefault().

Beispiele:


Versuchen wir anhand von Beispielen zu verstehen:

Wir werden ein reines JAVASCRIPT-Beispiel sehen

Beispiel 1:

<div onclick='executeParent()'>
  <a href='https://stackoverflow.com' onclick='executeChild()'>Click here to visit stackoverflow.com</a>
</div>
<script>
  function executeChild() {
    alert('Link Clicked');
  }

  function executeParent() {
    alert('div Clicked');
  }
</script>

Führen Sie den obigen Code Sie den Hyperlink sehen ‚Klicken Sie hier stackoverflow.com besuchen‘ jetzt , wenn Sie auf diesen Link klicken Sie zuerst erhalten Sie die Javascript - Benachrichtigung erhalten Link geklickt haben Nächstes werden Sie die JavaScript - Benachrichtigung erhalten , div Clicked und sofort werden Sie umgeleitet stackoverflow.com.

Beispiel 2:

<div onclick='executeParent()'>
  <a href='https://stackoverflow.com' onclick='executeChild()'>Click here to visit stackoverflow.com</a>
</div>
<script>
  function executeChild() {
    event.preventDefault();
    event.currentTarget.innerHTML = 'Click event prevented'
    alert('Link Clicked');
  }

  function executeParent() {
    alert('div Clicked');
  }
</script>

Führen Sie den obigen Code Sie den Hyperlink sehen ‚Klicken Sie hier stackoverflow.com besuchen‘ jetzt , wenn Sie auf diesen Link klicken Sie zuerst erhalten Sie die Javascript - Benachrichtigung erhalten Link geklickt Als nächstes werden Sie die JavaScript - Benachrichtigung erhalten , div Clicked Weiter Sie werden sehen , den Hyperlink " Klicken Sie hier, um stackoverflow.com zu besuchen. Ersetzt durch den Text "Klickereignis verhindert", werden Sie nicht zu stackoverflow.com weitergeleitet. Dies liegt an der Methode event.preventDefault (), mit der verhindert wurde, dass die Standardklickaktion ausgelöst wird.

Beispiel 3:

<div onclick='executeParent()'>
  <a href='https://stackoverflow.com' onclick='executeChild()'>Click here to visit stackoverflow.com</a>
</div>
<script>
  function executeChild() {
    event.stopPropagation();
    event.currentTarget.innerHTML = 'Click event prevented'
    alert('Link Clicked');
  }

  function executeParent() {
    alert('div Clicked');
  }
</script>

Wenn Sie diesmal auf Link klicken, wird die Funktion executeParent () nicht aufgerufen und Sie erhalten diesmal nicht die JavaScript-Warnung div . Dies liegt daran, dass wir die Weitergabe an das übergeordnete div mithilfe der event.stopPropagation () -Methode verhindert haben. Als nächstes wird der Hyperlink "Klicken Sie hier, um stackoverflow.com zu besuchen" durch den Text "Klickereignis wird ausgeführt" ersetzt und Sie werden sofort zu stackoverflow.com weitergeleitet. Dies liegt daran, dass wir nicht verhindert haben, dass die Standardklickaktion dieses Mal mithilfe der event.preventDefault () -Methode ausgelöst wird.

Beispiel 4:

<div onclick='executeParent()'>
  <a href='https://stackoverflow.com' onclick='executeChild()'>Click here to visit stackoverflow.com</a>
</div>
<script>
  function executeChild() {
    event.preventDefault();
    event.stopPropagation();
    event.currentTarget.innerHTML = 'Click event prevented'
    alert('Link Clicked');
  }

  function executeParent() {
    alert('Div Clicked');
  }
</script>

Wenn Sie auf den Link klicken, wird die Funktion executeParent () nicht aufgerufen und Sie erhalten keine Javascript-Warnung. Dies liegt daran, dass wir die Weitergabe an das übergeordnete div mithilfe der event.stopPropagation () -Methode verhindert haben. Als nächstes wird der Hyperlink "Klicken Sie hier, um stackoverflow.com zu besuchen" durch den Text "Klickereignis verhindert" ersetzt und Sie werden nicht zu stackoverflow.com weitergeleitet. Dies liegt daran, dass wir verhindert haben, dass die Standardklickaktion dieses Mal mithilfe der event.preventDefault () -Methode ausgelöst wird.

Beispiel 5:

Für die Rückgabe falsch habe ich drei Beispiele und alle scheinen genau dasselbe zu tun (nur falsch zurückzugeben), aber in Wirklichkeit sind die Ergebnisse ganz unterschiedlich. Hier ist, was in jedem der oben genannten Fälle tatsächlich passiert.

Fälle:

  1. Die Rückgabe von false von einem Inline-Ereignishandler verhindert, dass der Browser zur Linkadresse navigiert, verhindert jedoch nicht, dass sich das Ereignis über das DOM ausbreitet.
  2. Die Rückgabe von false von einem jQuery-Ereignishandler verhindert, dass der Browser zur Linkadresse navigiert, und verhindert, dass sich das Ereignis über das DOM ausbreitet.
  3. Die Rückgabe von false von einem regulären DOM-Ereignishandler bewirkt absolut nichts.

Werden alle drei Beispiele sehen.

  1. Inline return false.

<div onclick='executeParent()'>
  <a href='https://stackoverflow.com' onclick='return false'>Click here to visit stackoverflow.com</a>
</div>
<script>
  var link = document.querySelector('a');

  link.addEventListener('click', function() {
    event.currentTarget.innerHTML = 'Click event prevented using inline html'
    alert('Link Clicked');
  });


  function executeParent() {
    alert('Div Clicked');
  }
</script>

  1. Rückgabe von false von einem jQuery-Ereignishandler.

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
  <a href='https://stackoverflow.com'>Click here to visit stackoverflow.com</a>
</div>
<script>
  $('a').click(function(event) {
    alert('Link Clicked');
    $('a').text('Click event prevented using return FALSE');
    $('a').contents().unwrap();
    return false;
  });
  $('div').click(function(event) {
    alert('Div clicked');
  });
</script>

  1. Rückgabe von false von einem regulären DOM-Ereignishandler.

<div onclick='executeParent()'>
  <a href='https://stackoverflow.com' onclick='executeChild()'>Click here to visit stackoverflow.com</a>
</div>
<script>
  function executeChild() {
    event.currentTarget.innerHTML = 'Click event prevented'
    alert('Link Clicked');
    return false
  }

  function executeParent() {
    alert('Div Clicked');
  }
</script>

Hoffe, diese Beispiele sind klar. Versuchen Sie, alle diese Beispiele in einer HTML-Datei auszuführen, um zu sehen, wie sie funktionieren.

Keval Bhatt
quelle
1
Gute Beispiele, wäre aber ohne jQuery noch besser gewesen, weil jQuery das Ereignisobjekt fälscht, also ist das technisch anders.
Rudie
1
@ Rudie Ich habe meine Antwort aktualisiert und jquery daraus entfernt und auch ein Beispiel für die Rückgabe false hinzugefügt.
Keval Bhatt
17

Dies ist das Zitat von hier

Event.preventDefault

Die PreventDefault-Methode verhindert, dass ein Ereignis seine Standardfunktionalität ausführt. Beispielsweise würden Sie verhindern, dass DefaultDefault für ein A-Element verwendet wird, um zu verhindern, dass das Klicken auf dieses Element die aktuelle Seite verlässt:

//clicking the link will *not* allow the user to leave the page 
myChildElement.onclick = function(e) { 
    e.preventDefault(); 
    console.log('brick me!'); 
};

//clicking the parent node will run the following console statement because event propagation occurs
logo.parentNode.onclick = function(e) { 
    console.log('you bricked my child!'); 
};

Während die Standardfunktionalität des Elements blockiert ist, sprudelt das Ereignis weiterhin im DOM.

Event.stopPropagation

Die zweite Methode, stopPropagation, ermöglicht die Ausführung der Standardfunktionalität des Ereignisses, verhindert jedoch die Weitergabe des Ereignisses:

//clicking the element will allow the default action to occur but propagation will be stopped...
myChildElement.onclick = function(e) { 
    e.stopPropagation();
    console.log('prop stop! no bubbles!'); 
};

//since propagation was stopped by the child element's onClick, this message will never be seen!
myChildElement.parentNode.onclick = function(e) { 
    console.log('you will never see this message!'); 
};

stopPropagation verhindert effektiv, dass übergeordnete Elemente von einem bestimmten Ereignis in seinem untergeordneten Element erfahren.

Während eine einfache Stoppmethode es uns ermöglicht, Ereignisse schnell zu verarbeiten, ist es wichtig zu überlegen, was genau mit dem Sprudeln geschehen soll. Ich wette, alles, was ein Entwickler wirklich will, ist, 90% der Zeit Default zu verhindern! Wenn Sie ein Ereignis falsch "stoppen", kann dies zu zahlreichen Problemen führen. Ihre Plugins funktionieren möglicherweise nicht und Ihre Plugins von Drittanbietern sind möglicherweise blockiert. Oder noch schlimmer - Ihr Code beeinträchtigt andere Funktionen auf einer Site.

VladL
quelle
2

Event.preventDefault - Stoppt das Standardverhalten des Browsers. Nun kommt das Standardverhalten des Browsers. Angenommen, Sie haben ein Ankertag und es hat ein href-Attribut, und dieses Ankertag ist in einem div-Tag verschachtelt, das ein Klickereignis hat. Das Standardverhalten des Ankertags ist das Klicken auf das Ankertag, durch das navigiert werden soll. Event.preventDefault stoppt jedoch in diesem Fall die Navigation. Aber es stoppt niemals das Sprudeln des Ereignisses oder die Eskalation des Ereignisses, dh

<div class="container">
 <a href="#" class="element">Click Me!</a>
</div>

$('.container').on('click', function(e) {
 console.log('container was clicked');
});

$('.element').on('click', function(e) {
  e.preventDefault(); // Now link won't go anywhere
  console.log('element was clicked');
});

Das Ergebnis wird sein

"Element wurde angeklickt"

"Container wurde angeklickt"

Jetzt event.StopPropation stoppt das Sprudeln des Ereignisses oder die Eskalation des Ereignisses. Nun zum obigen Beispiel

$('.container').on('click', function(e) {
  console.log('container was clicked');
});

$('.element').on('click', function(e) {
  e.preventDefault(); // Now link won't go anywhere
  e.stopPropagation(); // Now the event won't bubble up
 console.log('element was clicked');
});

Ergebnis wird sein

"Element wurde angeklickt"

Weitere Informationen finden Sie unter diesem Link https://codeplanet.io/preventdefault-vs-stoppropagation-vs-stopimmediatepropagation/

Nayas Subramanian
quelle
1

event.preventDefault(); Stoppt die Standardaktion eines Elements.

event.stopPropagation(); Verhindert, dass das Ereignis in den DOM-Baum sprudelt, und verhindert, dass übergeordnete Handler über das Ereignis benachrichtigt werden.

Wenn beispielsweise ein Link mit einer Klickmethode innerhalb einer DIVoder FORMeiner Klickmethode angehängt ist, wird verhindert, dass die Klickmethode DIVoder FORMausgelöst wird.

Mike Clark
quelle
-3

$("#but").click(function(event){
console.log("hello");
  event.preventDefault();
 });


$("#foo").click(function(){
 alert("parent click event fired !");
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="foo">
  <button id="but">button</button>
</div>

Manish Singh
quelle