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


Quelle est la différence entre un événement bouillonnant et une capture? Parmi les deux, quel est le modèle le plus rapide et le meilleur à utiliser?


826
2018-01-06 15:44


origine


Réponses:


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

Avec le bouillonnement, l'événement est d'abord capturé et manipulé par l'élément le plus profond, puis propagé aux éléments extérieurs.

Avec la capture, l'événement est d'abord capturé par l'élément le plus externe et propagé aux éléments internes.

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

ruisseler, éclater

De retour dans l'ancien temps, Netscape préconisait la capture d'événements, tandis que Microsoft promouvait la création d'événements. Les deux font partie du W3C Événements de modèle d'objet de document norme (2000).

IE <9 utilisations seul événement bouillonnant, tandis que IE9 + et tous les principaux navigateurs prennent en charge les deux. D'un autre côté, le la performance de l'événement bouillonnant peut être légèrement inférieure pour les DOM complexes.

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

Exemple

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

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

En capturant le modèle, l'événement sera géré par le div d'abord (cliquez sur les gestionnaires d'événements dans le div tirera d'abord), puis dans le ul, puis au dernier élément de la cible, li.

Dans le modèle bouillonnant, le contraire se produira: l'événement sera d'abord géré par le li, puis par le ul, et enfin par le div élément.

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 se produit en premier, suivie par la phase de formation de bulles.

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

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>
<section id="log"></section>

Un autre exemple à JSFiddle.


1146
2018-01-06 15:47



La description:

quirksmode.org a une belle description de ceci. 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 se déclenche en premier, le gestionnaire d'événement de element2 tire en dernier.

Événement bouillonnant

Lorsque vous utilisez un événement bouillonnant

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

le gestionnaire d'événements de element2 se déclenche en premier, le gestionnaire d'événement de element1 tire en dernier.


Que 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 bien de déclencher les gestionnaires d'événements dans le bouillonner phase mais il peut également être nécessaire de les déclencher plus tôt.


455
2018-01-06 15:46



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 onCliquez. Maintenant, quand nous cliquons sur l'élément 2, alors eventHandler pour les deux éléments sera exécuté. Maintenant, la question est de savoir dans quel ordre l'événement sera exécuté. Si l'événement attaché à l'élément 1 s'exécute d'abord, il est appelé capture d'événement et si l'événement attaché à l'élément 2 s'exécute d'abord, cela s'appelle l'événement bubbling. Selon W3C l'événement commencera dans la phase de capture jusqu'à ce qu'il atteigne la cible revient à l'élément et alors il commence à bouillonner

Les états de capture et de formation de bulles 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 qu'il 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.


63
2018-03-04 12:45



J'ai trouvé ça tutoriel sur javascript.info être très clair en expliquant ce sujet. Et son résumé de 3 points à la fin parle vraiment aux points cruciaux. Je le cite ici:

  1. Les événements d'abord sont capturés jusqu'à la cible la plus profonde, puis montent en bulle. Dans   IE <9 ils ne font que bouillonner.
  2. Tous les manipulateurs travaillent sur des scènes exceptionnelles   addEventListener avec le dernier argument true, qui est le seul moyen de   attraper l'événement sur la scène de capture.
  3. Bubbling / capture peut être   arrêté par event.cancelBubble = true (IE) ou event.stopPropagation ()   pour les autres navigateurs.

23
2018-05-14 08:51



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

Notez que la compatibilité du navigateur n'est pas encore déterminée. Je l'ai testé sur Chrome (66.0.3359.181) et Firefox (59.0.3) et il est supporté ici.

Expansion sur le déjà excellent extrait de la réponse acceptée, c'est la sortie en utilisant le eventPhase propriété

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>


0
2018-05-29 07:31