javascript doesn't - Was ist der Unterschied zwischen event.stopPropagation und event.preventDefault?




work d3 (6)

Sie scheinen das Gleiche zu tun ... Ist man modern und alt? Oder werden sie von verschiedenen Browsern unterstützt?

Wenn ich selbst mit Ereignissen handle (ohne Rahmen), suche ich immer nach beiden und führe beide aus, falls vorhanden. (Ich node.addEventListener auch return false , aber ich habe das Gefühl, dass es nicht mit Ereignissen funktioniert, die mit node.addEventListener ).

Also warum beides? Sollte ich nach beiden suchen? Oder gibt es tatsächlich einen Unterschied?

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


Answers

$("#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>


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

event.stopPropagation(); Verhindert, dass das Ereignis die DOM-Struktur aufblubbert, und verhindert, dass alle übergeordneten Handler über das Ereignis benachrichtigt werden.

Wenn beispielsweise eine Verknüpfung mit einer angefügten Klickmethode in einem DIV oder einer FORM , an die auch eine Klickmethode angehängt ist, wird verhindert, dass die DIV oder FORM ausgelöst wird.


Dies ist das Zitat von here

Ereignis.präventDefault

Die preventDefault-Methode verhindert, dass ein Ereignis seine Standardfunktionalität ausführt. Zum Beispiel würden Sie preventDefault für ein A-Element verwenden, um zu verhindern, dass 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 gemauert ist, sprudelt das Ereignis weiter durch das DOM.

Event.stopPropagation

Die zweite Methode, stopPropagation, ermöglicht die Standardfunktion des Ereignisses, verhindert jedoch die Propagierung 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 die übergeordneten Elemente über ein bestimmtes Ereignis auf seinem Kindteil wissen.

Während eine einfache Stop-Methode uns erlaubt, Ereignisse schnell zu verarbeiten, ist es wichtig, darüber nachzudenken, was genau mit dem Blasen passieren soll. Ich würde wetten, dass alles, was ein Entwickler wirklich will, preventDefault 90% der Zeit ist! Falsches "Stoppen" eines Ereignisses könnte Ihnen zahlreiche Probleme bereiten; Ihre Plugins funktionieren möglicherweise nicht und Ihre Drittanbieter-Plugins könnten gemauert werden. Oder schlimmer noch - Ihr Code bricht andere Funktionen auf einer Website.


falsch zurückgeben;

return false; unterscheidet 3 Dinge, wenn Sie es nennen:

  1. event.preventDefault() - event.preventDefault() das Standardverhalten des Browsers.
  2. event.stopPropagation() - Verhindert, dass sich das Ereignis im DOM ausbreitet (oder "sprudelt").
  3. Stoppt die Ausführung von Callbacks und kehrt sofort beim Aufruf zurück.

Beachten Sie, dass sich dieses Verhalten von normalen (Nicht-jQuery-) Ereignisbehandlungsroutinen unterscheidet, bei denen insbesondere die return false das Bubbling des Ereignisses nicht stoppt.

Standard verhindern();

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

Wann man sie benutzt?

Wir wissen, was sie tun, aber wann sie zu verwenden sind? Einfach hängt es davon ab, was Sie erreichen möchten. Verwenden Sie preventDefault(); wenn Sie "nur" das Standardverhalten des Browsers verhindern wollen. 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 Sie wirklich wollen, ist preventDefault() .

Beispiele:

Lassen Sie uns versuchen, mit Beispielen zu verstehen:

Wir werden ein reines JAVASCRIPT-Beispiel sehen

Beispiel 1:

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

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

Führen Sie den obigen Code Sie sehen den Hyperlink "Klicken Sie hier, um .com zu besuchen" jetzt, wenn Sie auf diesen Link klicken, erhalten Sie zuerst die JavaScript-Warnung Link Klicken Sie auf Weiter, erhalten Sie die JavaScript-Alert div Klicken Sie auf und sofort werden Sie weitergeleitet .com.

Beispiel 2:

<div onclick='executeParent()'>
  <a href='https://.com' onclick='executeChild()'>Click here to visit .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 sehen den Hyperlink "Klicken Sie hier, um .com zu besuchen" jetzt, wenn Sie auf diesen Link klicken, erhalten Sie zuerst die JavaScript-Warnung Link geklickt Weiter erhalten Sie die JavaScript-Alert- div Klicken Sie auf Weiter Sie werden den Hyperlink sehen ' Klicken Sie hier, um .com zu besuchen, ersetzt durch den Text "Click event prevented" und Sie werden nicht zu .com weitergeleitet. Dies liegt an der event.preventDefault () -Methode, die wir verwendet haben, um zu verhindern, dass die Standardklickaktion ausgelöst wird.

Beispiel 3:

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

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

Dieses Mal, wenn Sie auf Link klicken, wird die Funktion executeParent () nicht aufgerufen und Sie werden nicht das Javascript Alert div bekommen. Klicken Sie dieses Mal. Dies liegt daran, dass wir die Weitergabe an das Eltern-Div mithilfe der event.stopPropagation () -Methode verhindert haben. Als Nächstes sehen Sie den Hyperlink "Klicken Sie hier, um .com zu besuchen", ersetzt durch den Text "Click Event wird ausgeführt" und sofort werden Sie zu .com weitergeleitet. Dies liegt daran, dass wir die Standard-Klickaktion nicht davon abgehalten haben, diesen Zeitpunkt mit der event.preventDefault () -Methode auszulösen.

Beispiel 4:

<div onclick='executeParent()'>
  <a href='https://.com' onclick='executeChild()'>Click here to visit .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 Eltern-Div mithilfe der event.stopPropagation () -Methode verhindert haben. Als Nächstes sehen Sie den Hyperlink "Klicken Sie hier, um .com zu besuchen", ersetzt durch den Text "Click event prevented" und Sie werden nicht zu .com weitergeleitet. Dies liegt daran, dass wir verhindert haben, dass die Standard-Klickaktion diesen Zeitpunkt mit der Methode event.preventDefault () ausgelöst hat.

Beispiel 5:

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

Fälle:

  1. Wenn false von einer Inline-Ereignisbehandlungsroutine zurückgegeben wird, kann der Browser nicht zur Linkadresse navigieren, das Ereignis wird jedoch nicht durch das DOM weitergeleitet.
  2. Wenn false von einer jQuery-Ereignisbehandlungsroutine zurückgegeben wird, wird verhindert, dass der Browser zur Linkadresse navigiert, und das Ereignis wird nicht durch das DOM weitergeleitet.
  3. Die Rückgabe von false aus einem regulären DOM-Event-Handler tut absolut nichts.

Werde alle drei Beispiele sehen.

  1. Inline-Rückgabe false.

<div onclick='executeParent()'>
  <a href='https://.com' onclick='return false'>Click here to visit .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 aus einem jQuery-Event-Handler.

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
  <a href='https://.com'>Click here to visit .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. False aus einem regulären DOM-Event-Handler zurückgeben.

<div onclick='executeParent()'>
  <a href='https://.com' onclick='executeChild()'>Click here to visit .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.


Von quirksmode.org

Ereigniserfassung

Wenn Sie Ereigniserfassung verwenden

               | |
---------------| |-----------------
| element1     | |                |
|   -----------| |-----------     |
|   |element2  \ /          |     |
|   -------------------------     |
|        Event CAPTURING          |
-----------------------------------

Der Ereignishandler von element1 wird zuerst ausgelöst, der Ereignishandler von element2 wird zuletzt ausgelöst.

Ereignis sprudelt

Wenn Sie Ereignisblasen verwenden
               / \
---------------| |-----------------
| element1     | |                |
|   -----------| |-----------     |
|   |element2  | |          |     |
|   -------------------------     |
|        Event 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 dann erneut aufbläht .

                 | |  / \
-----------------| |--| |-----------------
| element1       | |  | |                |
|   -------------| |--| |-----------     |
|   |element2    \ /  | |          |     |
|   --------------------------------     |
|        W3C event model                 |
------------------------------------------

Von https://www.w3.org/TR/DOM-Level-2-Events/events.html

Wenn der aufzeichnende EventListener verhindern möchte, dass eine weitere Verarbeitung des Ereignisses stattfindet, kann er die stopPropagation-Methode der Event-Schnittstelle aufrufen. Dies verhindert den weiteren Versand des Ereignisses, obwohl zusätzliche EventListener, die auf derselben Hierarchieebene registriert sind, das Ereignis erhalten. Sobald die Methode stopPropagation eines Ereignisses aufgerufen wurde, haben weitere Aufrufe dieser Methode keine zusätzliche Wirkung. Wenn keine weiteren Capturer vorhanden sind und stopPropagation nicht aufgerufen wurde, löst das Ereignis die entsprechenden EventListeners auf dem Ziel selbst aus.

Und zum Blubbern:

Jeder Event-Handler kann die weitere Ereignisausbreitung durch Aufruf der stopPropagation-Methode der Event-Schnittstelle verhindern. Wenn ein EventListener diese Methode aufruft, werden alle zusätzlichen EventListener auf dem aktuellen EventTarget ausgelöst, aber die Blasenbildung wird auf dieser Ebene beendet. Es ist nur ein Aufruf von stopPropagation erforderlich, um weiteres Blubbern zu verhindern.

Beispiele :

HTML

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

JavaScript

var el = document.getElementById("c");
function captureOnClickA(e){
    el.innerHTML += "DIV event capture<br>";
}
function captureOnClickB(e){
    el.innerHTML += "A event capture<br>";
}
function bubblingOnClickA(e){
    el.innerHTML += "DIV event bubbling<br>";
}
function bubblingOnClickB(e){
    el.innerHTML += "A event bubbling<br>";
}
document.getElementById("a").addEventListener("click",captureOnClickA, true);
document.getElementById("b").addEventListener("click",captureOnClickB, true);
document.getElementById("a").addEventListener("click",bubblingOnClickA, false);
document.getElementById("b").addEventListener("click",bubblingOnClickB, false);

Demo , In diesem Beispiel werden vier Ereignis-Listener ausgeführt, und im Browser wird ein neuer Tab geöffnet. Die Ausgabe ist:

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

Ändern der ersten Funktion zu:

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

Wird in dieser Ausgabe resultieren:

DIV event capture

was bedeutet, dass die Abwärtsausbreitung des Ereignisses gestoppt wird und auch seine Aufwärtsausbreitung. Demo . Aber es wird nicht verhindern, dass der Tab geöffnet wird.

Hinzufügen von stopPropagation() zu

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

Demo oder

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

Demo , führt zu der gleichen Ausgabe, da sie sich auf dem aktuellen EventTarget befinden:

DIV event capture
A event capture
A event bubbling

In diesen beiden Fällen verhinderte das Ereignis, bis zum Elternteil zu sprudeln. Auch diese zwei verhindern nicht das Öffnen der Lasche. Um zu verhindern, dass die Registerkarte geöffnet wird, müssen wir preventDefault() , um die Standard-Browser-Aktion zu verhindern:

function captureOnClickA(e){
    el.innerHTML += "DIV event capture<br>";
    e.stopPropagation();
    e.preventDefault();
}

Jetzt wird die Registerkarte nicht geöffnet und nur einer der Ereignis-Listener wird ausgeführt. Demo .


Aus meiner Erfahrung gibt es mindestens einen klaren Vorteil, wenn Sie event.preventDefault () über return false verwenden. Angenommen, Sie erfassen das Click-Ereignis mit einem Ankertag. Andernfalls wäre dies ein großes Problem, wenn der Benutzer von der aktuellen Seite weg navigiert würde. Wenn Ihr Click-Handler return false verwendet, um die Browsernavigation zu verhindern, besteht die Möglichkeit, dass der Interpreter die return-Anweisung nicht erreicht und der Browser das Standardverhalten des Ankertags ausführt.

$('a').click(function (e) {
  // custom handling here

  // oops...runtime error...where oh where will the href take me?

  return false;
});

Die Verwendung von event.preventDefault () hat den Vorteil, dass Sie dies als erste Zeile im Handler hinzufügen können. Dadurch wird sichergestellt, dass das Standardverhalten des Ankers nicht ausgelöst wird, unabhängig davon, ob die letzte Zeile der Funktion nicht erreicht wird (z. B. Laufzeitfehler.) ).

$('a').click(function (e) {
  e.preventDefault();

  // custom handling here

  // oops...runtime error, but at least the user isn't navigated away.
});




javascript events preventdefault stoppropagation