DOM Evento de burbujas y captura


Ejemplo

Los eventos activados en elementos DOM no solo afectan el elemento al que se dirigen. Cualquiera de los ancestros del objetivo en el DOM también puede tener la oportunidad de reaccionar ante el evento. Considere el siguiente documento:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
</head>
<body>
  <p id="paragraph">
    <span id="text">Hello World</span>
  </p>
</body>
</html>

Si solo agregamos escuchas a cada elemento sin ninguna opción, entonces activamos un clic en el intervalo ...

document.body.addEventListener('click', function(event) {
  console.log("Body clicked!");
});
window.paragraph.addEventListener('click', function(event) {
  console.log("Paragraph clicked!");
});
window.text.addEventListener('click', function(event) {
  console.log("Text clicked!");
});

window.text.click();

... entonces el evento se propagará a través de cada antepasado, activando cada controlador de clic en el camino:

Text clicked!
Paragraph clicked!
Body clicked!

Si desea que uno de sus manejadores impida que el evento event.stopPropagation() más manejadores, puede llamar al método event.stopPropagation() . Por ejemplo, si reemplazamos nuestro segundo controlador de eventos con esto:

window.paragraph.addEventListener('click', function(event) {
  console.log("Paragraph clicked, and that's it!");
  event.stopPropagation();
});

Veríamos la siguiente salida, con el manejador de click body nunca activado:

Text clicked!
Paragraph clicked, and that's it!

Finalmente, tenemos la opción de agregar detectores de eventos que se activan durante la " captura " en lugar de burbujear. Antes de que un evento brote de un elemento a través de sus antepasados, primero se "captura" hasta el elemento a través de sus antepasados. Se agrega una escucha de captura especificando true o {capture: true} como el tercer argumento opcional para addEventListener . Si agregamos los siguientes oyentes a nuestro primer ejemplo anterior:

document.body.addEventListener('click', function(event) {
  console.log("Body click captured!");
}, true);
window.paragraph.addEventListener('click', function(event) {
  console.log("Paragraph click captured!");
}, true);
window.text.addEventListener('click', function(event) {
  console.log("Text click captured!");
}, true);

Obtendremos la siguiente salida:

Body click captured!
Paragraph click captured!
Text click captured!
Text clicked!
Paragraph clicked!
Body clicked!

Por defecto, los eventos se escuchan en la fase de propagación. Para cambiar esto, puede especificar en qué fase se escucha el evento especificando el tercer parámetro en la función addEventListener. (Para aprender sobre la captura y el burbujeo, verifique los comentarios )

element.addEventListener(eventName, eventHandler, useCapture)

useCapture: true significa escuchar el evento cuando se está ejecutando en el árbol DOM. false significa escuchar el evento mientras sube el árbol DOM.

window.addEventListener("click", function(){alert('1: on bubble')}, false);
window.addEventListener("click", function(){alert('2: on capture')}, true);

Los cuadros de alerta aparecerán en este orden:

  • 2: en la captura
  • 1: en burbuja

Casos de uso en el mundo real.

El Evento de captura se enviará antes del Evento de burbuja, por lo que puede asegurarse de que un evento se escuche primero si lo escucha en su fase de captura.

Si está escuchando un evento de clic en un elemento padre y otro en su hijo, puede escuchar primero al niño o al padre, según cómo cambie el parámetro useCapture.

en el burbujeo, el evento hijo se llama primero, en la captura, el padre primero

en el burbujeo, el evento hijo se llama primero, en la captura, el padre primero

HTML:

<div id="parent">
   <div id="child"></div>
</div>

Javascript:

child.addEventListener('click', function(e) {
   alert('child clicked!');
});

parent.addEventListener('click', function(e) {
   alert('parent clicked!');
}, true);

Si se establece fiel al evento primario, el EventListener activará primero el escucha principal.

Combinado con e.stopPropagation () puede evitar que el evento active al oyente de eventos secundario o al padre. (más sobre eso en el siguiente ejemplo)