DOM Evento che bolle e cattura

Esempio

Gli eventi attivati ​​sugli elementi DOM non riguardano solo l'elemento a cui sono indirizzati. Qualunque degli antenati del bersaglio nel DOM può anche avere la possibilità di reagire all'evento. Considera il seguente documento:

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

Se aggiungiamo solo listener ad ogni elemento senza opzioni, attiviamo un clic sull'intervallo ...

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

... allora l'evento sarà bolla attraverso ogni antenato, innescando ogni gestore click sulla strada:

Text clicked!
Paragraph clicked!
Body clicked!

Se vuoi che uno dei tuoi gestori interrompa l'evento dall'attivazione di altri gestori, può chiamare il metodo event.stopPropagation() . Ad esempio, se sostituiamo il nostro secondo gestore di eventi con questo:

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

Vedremmo il seguente output, con il gestore di click body mai attivato:

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

Infine, abbiamo la possibilità di aggiungere listener di eventi che si attivano durante " capture " anziché bubbling. Prima che un evento esploda da un elemento attraverso i suoi antenati, viene prima "catturato" fino all'elemento attraverso i suoi antenati. Un listener di acquisizione viene aggiunto specificando true o {capture: true} come terzo argomento opzionale per addEventListener . Se aggiungiamo i seguenti ascoltatori al nostro primo esempio sopra:

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

Otterremo il seguente risultato:

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

Per impostazione predefinita, gli eventi vengono ascoltati nella fase di bubbling. Per cambiare questo è possibile specificare in quale fase viene ascoltato l'evento specificando il terzo parametro nella funzione addEventListener. (Per informazioni su come catturare e gorgogliare, consultare i commenti )

element.addEventListener(eventName, eventHandler, useCapture)

useCapture: true significa ascoltare l'evento quando scende nell'albero DOM. false significa ascoltare l'evento mentre sale sull'albero DOM.

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

Le caselle di avviso compariranno in questo ordine:

  • 2: in fase di acquisizione
  • 1: sulla bolla

Casi d'uso del mondo reale

L'evento Capture verrà inviato prima di Bubble Event, quindi è possibile assicurarsi che un evento sia ascoltato per primo se lo si ascolta nella sua fase di acquisizione.

se stai ascoltando un evento click su un elemento genitore, e un altro su suo figlio, puoi prima ascoltare il bambino o il genitore, a seconda di come cambi il parametro useCapture.

nel bubbling, l'evento figlio viene chiamato per primo, nella cattura, il genitore prima

nel bubbling, l'evento figlio viene chiamato per primo, nella cattura, il genitore prima

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

Impostazione true per il genitore eventListener attiverà prima il listener genitore.

Combinato con e.stopPropagation () è possibile impedire all'evento di attivare il listener di eventi figlio / o il genitore. (altro su questo nel prossimo esempio)