Qu'est-ce que l'événement bouillonnant et capturer?

Quelle est la différence entre un événement bouillonnant et un événement capturant? Des deux, lequel est le plus rapide et le meilleur modèle à utiliser?

849
demandé sur bjb568 2011-01-06 18:44:43

5 réponses

event bubbling and capturing sont deux façons de propager un événement dans L'API DOM HTML, 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é une poignée pour cet événement. Le mode de propagation de l'événement détermine dans l'ordre dans lequel les éléments reçoivent l'événement .

avec des bulles, l'événement est d'abord capturé et manipulé par l'élément le plus intérieur, puis propagé aux éléments extérieurs.

avec capturing, l'événement est d'abord capturé par l'élément extérieur et propagé aux éléments intérieurs.

la capture est aussi appelée "ruissellement", ce qui aide à se souvenir de l'ordre de propagation:

goutte vers le bas, bulle vers le haut

à L'époque, Netscape préconisait la capture d'événements, tandis que Microsoft favorisait le bouillonnement d'événements. Tous deux font partie de L'objet du document du W3C. Modèle Événements standard (2000).

IE < 9 utilise bubbling only event , tandis que IE9+ et tous les principaux navigateurs prennent en charge les deux. D'autre part, la performance de l'événement de bouillonnement peut être légèrement inférieure pour les DOMs complexes.

nous pouvons utiliser le addEventListener(type, listener, useCapture) pour enregistrer les gestionnaires d'événements en mode bubbling (par défaut) ou en mode de capture. Pour utiliser le modèle de capture passer le troisième argument comme 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 traité par le div d'abord (les gestionnaires d'événements de clic dans le div tireront en premier), puis dans le ul , puis à la dernière dans l'élément cible, li .

dans le modèle à bulles, le contraire sera l'événement sera d'abord traitée par le li , puis par le ul , et enfin par la div élément.

pour en savoir plus, lisez

  • "1519150920 de l'Événement" l'Ordre sur QuirksMode
  • addEventListener on MDN
  • "1519600920 Événements" Avancé sur QuirksMode

dans le 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 de l'événement se produit d'abord, suivie par la phase de bouillonnement.

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 .

1180
répondu Arun P Johny 2017-07-12 16:07:33

Description:

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

capture D'événement

lorsque vous utilisez la capture d'événements

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

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

"151930920 de l'Événement" bouillonnement

quand vous utilisez événement barbotage

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

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


Ce qu'il faut utiliser?

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

460
répondu Felix Kling 2011-01-06 15:46:18

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énement avec les deux éléments permet de dire onClick. Maintenant, lorsque nous cliquons sur l'élément 2, eventHandler pour les deux éléments sera exécuté. Maintenant, la question Est de savoir dans quel ordre l'événement va s'exécuter. Si l'événement attaché à l'élément 1 s'exécute en premier, il est appelé event capturing et si l'événement attaché à l'élément 2 s'exécute en premier, il est appelé event bubbling. Comme par W3C l'événement va commencer dans la phase de capture jusqu'à ce qu'il atteigne la cible revient à l'élément et puis il commence à bouillonner

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

eventTarget.la méthode addEventListener(type,à l'écoute,[,useCapture]);

par défaut useCapture est false. Cela signifie qu'il est en 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>

essayez de changer vrai et faux.

64
répondu dinesh_malhotra 2017-06-25 22:16:47

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

  1. les événements sont d'abord captés vers la cible la plus profonde, puis vers le haut. Dans C'est-à-dire<9 ils ne font que des bulles.
  2. tous les manipulateurs travaillent sur les exceptions de phase bouillonnante addEventListener avec le dernier argument vrai, qui est la seule façon de captez l'événement sur la scène de capture.
  3. Bouillonnement/capture peut être arrêté par événement.cancelBubble=true (IE) ou event.stopPropagation() pour les autres navigateurs.
23
répondu gm2008 2015-05-14 08:51:09

il y a aussi la propriété Event.eventPhase 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é là.

étendre sur le déjà grand extrait de la réponse acceptée , c'est la sortie en utilisant le eventPhase propriété 151980920"

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>
1
répondu Adelin 2018-05-29 12:54:00