web-dev-qa-db-fra.com

Qu'est-ce que l'événement bouillonne et capture?

Quelle est la différence entre un événement bouillonnant et une capture? Quand faut-il utiliser le bullage contre la capture?

967
Arun P Johny

La propagation d'événement et la capture sont deux méthodes de propagation d'événement dans l'API HTML DOM, lorsqu'un événement se produit dans un élément à l'intérieur d'un autre élément et que les deux éléments ont enregistré un descripteur pour cet événement. Le mode de propagation d'événement détermine in dans quel ordre les éléments reçoivent l'événement .

Avec le bullage, l'événement est d'abord capturé et traité par l'élément le plus à l'intérieur, puis propagé aux éléments externes.

Avec la capture, l’événement est d’abord capturé par l’élément le plus à l’extérieur et propagé aux éléments internes.

La capture est également appelée "ruissellement", ce qui permet de mémoriser l'ordre de propagation:

ruisseler, bouillir

À l'époque, Netscape préconisait la capture d'événements, tandis que Microsoft promouvait la diffusion d'événements. Les deux font partie du W3C Événements de modèle d'objet de document standard (2000).

IE <9 utilise niquement les événements , alors que IE9 + et tous les principaux navigateurs prennent en charge les deux. D'autre part, la performance de la propagation d'événements peut être légèrement inférieure pour les DOM complexes.

Nous pouvons utiliser la addEventListener(type, listener, useCapture) pour enregistrer les gestionnaires d'événements en mode de création de bulles (par défaut) ou de capture. Pour utiliser le modèle de capture, transmettez le troisième argument sous la forme true.

Exemple

<div>
    <ul>
        <li></li>
    </ul>
</div>

Dans la structure ci-dessus, supposons qu'un événement de clic se soit produit dans l'élément li.

Dans le modèle de capture, l'événement sera d'abord traité par le div (les gestionnaires d'événements de clic dans le div se déclencheront en premier), puis dans le ul, puis en dernier dans l'élément cible. , li.

Dans le modèle à bulles, c'est l'inverse qui se produira: l'événement sera d'abord traité par le li, puis par le ul et enfin par l'élément div.

Pour plus d'informations, voir

Dans l'exemple ci-dessous, si vous cliquez sur l'un des éléments en surbrillance, vous pouvez voir que la phase de capture du flux de propagation d'événement a lieu en premier lieu, suivie de la phase de propagation.

var logElement = document.getElementById('log');

function log(msg) {
    logElement.innerHTML += ('<p>' + msg + '</p>');
}

function capture() {
    log('capture: ' + this.firstChild.nodeValue.trim());
}

function bubble() {
    log('bubble: ' + this.firstChild.nodeValue.trim());
}

function clearOutput() {
    logElement.innerHTML = "";
}

var divs = document.getElementsByTagName('div');
for (var i = 0; i < divs.length; i++) {
    divs[i].addEventListener('click', capture, true);
    divs[i].addEventListener('click', bubble, false);
}
var clearButton = document.getElementById('clear');
clearButton.addEventListener('click', clearOutput);
p {
    line-height: 0;
}

div {
    display:inline-block;
    padding: 5px;

    background: #fff;
    border: 1px solid #aaa;
    cursor: pointer;
}

div:hover {
    border: 1px solid #faa;
    background: #fdd;
}
<div>1
    <div>2
        <div>3
            <div>4
                <div>5</div>
            </div>
        </div>
    </div>
</div>
<button id="clear">clear output</button>
<section id="log"></section>

n autre exemple chez JSFiddle .

1349
Arun P Johny

Description:

quirksmode.org en a une bonne description. En un mot (copié de quirksmode):

Capture d'événement

Lorsque vous utilisez la capture d'événement

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

le gestionnaire d'événements de element1 est déclenché en premier, le gestionnaire d'événements de element2 en dernier.

Événement bouillonnant

Lorsque vous utilisez l'événement bouillonnant

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

le gestionnaire d'événements de element2 est déclenché en premier, le gestionnaire d'événements de element1 en dernier.


Que faut-il utiliser?

Cela dépend de ce que vous voulez faire. Il n'y a pas mieux. La différence est l'ordre d'exécution des gestionnaires d'événements. La plupart du temps, il sera utile de renvoyer les gestionnaires d’événements dans la phase bubbling, mais il peut également être nécessaire de les renvoyer plus tôt.

494
Felix Kling

S'il y a deux éléments élément 1 et élément 2. L'élément 2 est à l'intérieur de l'élément 1 et nous attachons un gestionnaire d'événements avec les deux éléments, disons onClick. Maintenant, lorsque nous cliquons sur l'élément 2, eventHandler sera exécuté pour les deux éléments. Maintenant, voici la question dans quel ordre l'événement sera exécuté. Si l'événement associé à l'élément 1 s'exécute en premier, il est appelé capture d'événement et si l'événement associé à l'élément 2 s'exécute en premier, on parle d'événement bouillonnant. Selon le W3C, l’événement débutera dans la phase de capture jusqu’à ce que la cible revienne à l’élément, puis il commence à bouillonner.

Les états de capture et de bullage sont connus par le paramètre useCapture de la méthode addEventListener

eventTarget.addEventListener (type, écouteur, [ useCapture]);

Par défaut, useCapture est false. Cela signifie que c'est dans la phase de bouillonnement.

var div1 = document.querySelector("#div1");
var div2 = document.querySelector("#div2");

div1.addEventListener("click", function (event) {
  alert("you clicked on div 1");
}, true);

div2.addEventListener("click", function (event) {
  alert("you clicked on div 2");
}, false);
#div1{
  background-color:red;
  padding: 24px;
}

#div2{
  background-color:green;
}
<div id="div1">
  div 1
  <div id="div2">
    div 2
  </div>
</div>

S'il vous plaît essayez de changer vrai et faux.

68
dinesh_malhotra

J'ai trouvé ceci tutoriel sur javascript.info pour être très clair dans l'explication de ce sujet. Et son résumé en 3 points à la fin parle vraiment des points cruciaux. Je le cite ici:

  1. Les événements sont d'abord capturés jusqu'à la cible la plus profonde, puis remontés. Dans IE <9, ils ne font que des bulles.
  2. Tous les gestionnaires travaillant sur l'étape de formation de bulles excluent addEventListener avec le dernier argument true, qui est le seul moyen de capturer l'événement sur l'étape de capture.
  3. Le bouillonnement/capture peut être arrêté avec event.cancelBubble=true (IE) ou event.stopPropagation() pour les autres navigateurs.
25
gm2008

Il y a aussi la propriété Event.eventPhase qui peut vous dire si l'événement est sur la cible ou provient d'ailleurs.

Notez que la compatibilité du navigateur n’a pas encore été déterminée. Je l'ai testé sur Chrome (66.0.3359.181) et Firefox (59.0.3), où il est pris en charge.

En développant le déjà grand extrait de la réponse acceptée , il s'agit de la sortie utilisant la propriété eventPhase

_var logElement = document.getElementById('log');

function log(msg) {
  if (logElement.innerHTML == "<p>No logs</p>")
    logElement.innerHTML = "";
  logElement.innerHTML += ('<p>' + msg + '</p>');
}

function humanizeEvent(eventPhase){
  switch(eventPhase){
    case 1: //Event.CAPTURING_PHASE
      return "Event is being propagated through the target's ancestor objects";
    case 2: //Event.AT_TARGET
      return "The event has arrived at the event's target";
    case 3: //Event.BUBBLING_PHASE
      return "The event is propagating back up through the target's ancestors in reverse order";
  }
}
function capture(e) {
  log('capture: ' + this.firstChild.nodeValue.trim() + "; " + 
  humanizeEvent(e.eventPhase));
}

function bubble(e) {
  log('bubble: ' + this.firstChild.nodeValue.trim() + "; " + 
  humanizeEvent(e.eventPhase));
}

var divs = document.getElementsByTagName('div');
for (var i = 0; i < divs.length; i++) {
  divs[i].addEventListener('click', capture, true);
  divs[i].addEventListener('click', bubble, false);
}_
_p {
  line-height: 0;
}

div {
  display:inline-block;
  padding: 5px;

  background: #fff;
  border: 1px solid #aaa;
  cursor: pointer;
}

div:hover {
  border: 1px solid #faa;
  background: #fdd;
}_
_<div>1
  <div>2
    <div>3
      <div>4
        <div>5</div>
      </div>
    </div>
  </div>
</div>
<button onclick="document.getElementById('log').innerHTML = '<p>No logs</p>';">Clear logs</button>
<section id="log"></section>_
6
Adelin

Bubbling

  Event propagate to the Upto root element is Bubbling.

Capture

  Event propogate from body(root) element to eventTriggered Element is Capturing.
1
Kondal