javascript - working - stoppropagation vs preventdefault




¿Cuál es la diferencia entre event.stopPropagation y event.preventDefault? (5)

Terminología

Desde quirksmode.org :

Captura de eventos

Cuando usas captura de eventos

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

el controlador de eventos de element1 se activa primero, el controlador de eventos de element2 se activa en último lugar.

Evento burbujeante

Cuando usas un evento burbujeante

               / \
---------------| |-----------------
| element1     | |                |
|   -----------| |-----------     |
|   |element2  | |          |     |
|   -------------------------     |
|        Event BUBBLING           |
-----------------------------------

el controlador de eventos de element2 se activa primero, el controlador de eventos de element1 se activa en último lugar.

Cualquier evento que tenga lugar en el modelo de eventos W3C se captura primero hasta que alcanza el elemento objetivo y luego vuelve a aparecer .

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

Interfaz

Desde w3.org , para la captura de eventos :

Si el EventListener captura desea evitar que se siga procesando el evento, puede llamar al método stopPropagation de la interfaz del Event . Esto evitará un mayor envío del evento, aunque los EventListeners adicionales registrados en el mismo nivel jerárquico seguirán recibiendo el evento. Una vez que se ha llamado al método stopPropagation un evento, las llamadas posteriores a ese método no tienen ningún efecto adicional. Si no existen capturadores adicionales y no se ha llamado a stopPropagation , el evento activa los EventListeners apropiados en el propio destino.

Para evento de burbujeo :

Cualquier controlador de eventos puede optar por evitar una mayor propagación de eventos llamando al método stopPropagation de la interfaz de Event . Si cualquier EventListener llama a este método, todos los EventTarget adicionales en el EventTarget actual se activarán, pero el burbujeo cesará en ese nivel. Solo se requiere una llamada a stopPropagation para evitar más burbujas.

Para la cancelación del evento :

La cancelación se realiza llamando al método preventDefault del Event . Si uno o más EventListeners llaman a preventDefault durante cualquier fase del flujo de eventos, se cancelará la acción predeterminada.

Ejemplos

En los siguientes ejemplos, un clic en el hipervínculo en el navegador web activa el flujo del evento (se ejecutan los detectores de eventos) y la acción predeterminada del objetivo del evento (se abre una nueva pestaña).

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);

Ejemplo 1 : da como resultado la salida

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

Ejemplo 2 : agregar stopPropagation() a la función

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

resultados en la salida

DIV event capture

El detector de eventos impidió la propagación hacia arriba y hacia abajo del evento. Sin embargo, no impidió que la acción predeterminada (una nueva pestaña se abriera).

Ejemplo 3 : agregar stopPropagation() a la función

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

o la función

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

resultados en la salida

DIV event capture
A event capture
A event bubbling

Esto se debe a que ambos oyentes de eventos están registrados en el mismo destino de evento. Los oyentes del evento impidieron una mayor propagación hacia arriba del evento. Sin embargo, no impidieron que la acción predeterminada (una nueva pestaña se abriera).

Ejemplo 4 : agregar preventDefault() a cualquier función, por ejemplo

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

evita que una nueva pestaña se abra.

Parecen estar haciendo lo mismo ... ¿Es uno moderno y otro viejo? ¿O son compatibles con diferentes navegadores?

Cuando manejo los eventos por mí mismo (sin marco), siempre verifico ambos y ejecuto ambos si están presentes. (También return false , pero tengo la sensación de que no funciona con eventos adjuntos con node.addEventListener ).

Entonces, ¿por qué ambos? ¿Debo seguir revisando ambos? ¿O hay realmente una diferencia?

(Lo sé, muchas preguntas, pero todas son más o menos iguales)


Esta es la cita de here

Evento.preventDefault

El método preventDefault evita que un evento lleve a cabo su funcionalidad predeterminada. Por ejemplo, usaría preventDefault en un elemento A para dejar de hacer clic en ese elemento y dejar la página actual:

//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!'); 
};

Si bien la funcionalidad predeterminada del elemento está bloqueada, el evento continúa haciendo que el DOM se reinicie.

Event.stopPropagation

El segundo método, stopPropagation, permite que ocurra la funcionalidad predeterminada del evento, pero evita que el evento se propague:

//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 evita de manera efectiva que los elementos principales conozcan un evento determinado en su elemento secundario.

Si bien un método simple de detención nos permite manejar eventos rápidamente, es importante pensar qué es exactamente lo que quiere que suceda con el burbujeo. ¡Apostaría a que todo lo que un desarrollador realmente quiere es prevenir el defecto el 90% del tiempo! "Detener" incorrectamente un evento podría causarle numerosos problemas en la línea; Es posible que sus complementos no funcionen y que los complementos de terceros puedan ser bloqueados. O peor aún: su código rompe otras funciones de un sitio.


event.preventDefault(); Evita que la acción predeterminada de un elemento suceda.

event.stopPropagation(); Evita que el evento burbujee en el árbol DOM, evitando que se notifique al evento a los controladores principales.

Por ejemplo, si hay un enlace con un método de clic adjunto dentro de un DIV o FORM que también tiene un método de clic adjunto, evitará que se dispare el método de clic DIV o FORM .


stopPropagation evita que el evento stopPropagation en la cadena de eventos.

preventDefault evita la acción predeterminada que realiza el navegador en ese evento.

Digamos que tienes

<div id="foo">
 <button id="but" />
</div>

$("#foo").click(function() {
   // mouse click on div
});

$("#but").click(function(ev) {
   // mouse click on button
   ev.stopPropagation();
});

Ejemplo

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

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

Con stopPropagation solo se stopPropagation el botón de hacer clic en el controlador y el controlador de clic de divs nunca se dispara.

En este caso, como si simplemente preventDefault defecto, solo se detuvo la acción predeterminada de los navegadores, pero el controlador de clic del div todavía se dispara.

A continuación se muestran algunos documentos sobre los objetos de eventos DOM de MDN y MSDN

MDN:

Para IE9 y FF, puede usar preventDefault & stopPropagation.

Para admitir IE8 e inferior, reemplace stopPropagation con cancelBubble y reemplace preventDefault con returnValue


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







stoppropagation