1150 votes

Qu'est-ce que le bullage et la capture d'événements ?

Quelle est la différence entre le bouillonnement et la capture d'événements ? Quand faut-il utiliser le bullage ou la capture ?

3 votes

Je vous recommande ce lien utile : javascript.info/bubbling-and-capturing

0 votes

@CommunityAns : ce site est excellent, mais ce sujet, en particulier, est décrit de manière un peu confuse.

1609voto

Arun P Johny Points 151748

Le bullage et la capture d'événements sont deux modes de propagation d'événements 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 handle pour cet événement. Le mode de propagation des événements détermine dans 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 interne, puis propagé aux éléments externes.

Avec la capture, l'événement est d'abord capturé par l'élément le plus extérieur et propagé aux éléments intérieurs.

La capture est également appelée "trickling", ce qui permet de se souvenir de l'ordre de propagation :

ruisseler vers le bas, bouillonner vers le haut

Autrefois, Netscape préconisait la capture d'événements, tandis que Microsoft favorisait le bouillonnement d'événements. Les deux font partie du W3C Événements du modèle objet du document standard (2000).

IE < 9 utilise uniquement le bouillonnement d'événements alors que IE9+ et tous les principaux navigateurs prennent en charge les deux. D'autre part, le les performances du bullage d'événement peuvent être légèrement inférieures pour les DOM complexes.

Nous pouvons utiliser le addEventListener(type, listener, useCapture) pour enregistrer des gestionnaires d'événements en mode bulle (par défaut) ou en mode capture. Pour utiliser le modèle de capture, passez le troisième argument en tant que 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 champ li élément.

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

Dans le modèle de bouillonnement, c'est l'inverse qui se produit : l'événement est d'abord traité par la fonction 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 mis en évidence, vous pouvez voir que la phase de capture du flux de propagation des événements se produit en premier, suivie de la phase de bullage.

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>

Un autre exemple à JSFiddle .

45 votes

useCapture désormais pris en charge dans IE >= 9. fuente

7 votes

Je sais qu'il est trop tard pour faire un commentaire mais j'ai trouvé un bel article ici. catcode.com/domcontent/events/capture.html

4 votes

Est triclkling la même chose que capturing ? Crockford parle de Trickling v. Bubbling dans ce discours vidéo - youtube.com/watch?v=Fv9qT9joc0M&list=PL7664379246A246CB autour de 1 hr 5 minutes .

541voto

Felix Kling Points 247451

Description :

quirksmode.org en donne une bonne description. En résumé (copié de quirksmode) :

Capture d'événements

Lorsque vous utilisez la capture d'événements

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

le gestionnaire d'événements de l'élément 1 se déclenche en premier, le gestionnaire d'événements de l'élément 2 se déclenche en dernier.

Bulles d'événements

Lorsque vous utilisez le bouillonnement d'événements

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

le gestionnaire d'événements de l'élément 2 se déclenche en premier, le gestionnaire d'événements de l'élément 1 se déclenche en dernier.


Que faut-il utiliser ?

Cela dépend de ce que vous voulez faire. Il n'y a pas de meilleure solution. La différence réside dans l'ordre d'exécution des gestionnaires d'événements. La plupart du temps, il est préférable d'exécuter les gestionnaires d'événements dans l'ordre suivant bouillonnant mais il peut aussi être nécessaire de les licencier plus tôt.

0 votes

Les deux ne se produisent-ils pas, d'abord la capture et ensuite le bouillonnement, aussi qu'est-ce que l'événement de répartition ?

1 votes

Un exemple graphique est ici : javascript.info/bubbling-and-capturing

77voto

dinesh_malhotra Points 271

S'il y a deux éléments, l'élément 1 et l'élément 2. L'élément 2 est à l'intérieur de l'élément 1 et nous attachons un gestionnaire d'événement aux deux éléments, disons onClick. Maintenant, lorsque nous cliquons sur l'élément 2, le gestionnaire d'événement des 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 en premier, on parle de capture d'événement et si l'événement attaché à l'élément 2 s'exécute en premier, on parle de bouillonnement d'événement. Selon le W3C, l'événement commence dans la phase de capture jusqu'à ce qu'il atteigne la cible et revienne à l'élément, puis il commence à bouillonner.

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

eventTarget.addEventListener(type,listener,[,useCapture]) ;

Par défaut, useCapture est faux. 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 le vrai et le faux.

3 votes

@masterxilo : pas besoin de Fiddle, StackOverflow supporte maintenant code en ligne (extraits de pile) .

0 votes

Concernant the event will start in the capturing phase untill it reaches the target comes back to the element and then it starts bubbling . Je n'ai trouvé que le addEventListener a le paramètre useCapture qui peut être défini comme vrai ou faux ; et en HTML 4.0, les écouteurs d'événements étaient spécifiés comme attributs d'un élément y useCapture defaults to false . Pourriez-vous indiquer un lien vers une spécification qui confirme ce que vous avez écrit ?

32voto

gm2008 Points 257

J'ai trouvé ceci tutoriel à 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 buller.
  2. Tous les manipulateurs travaillent sur l'étape de bouillonnement sauf addEventListener avec le dernier argument true qui est le seul moyen de d'assister à l'événement en capturant la scène.
  3. Le bullage/captage peut être arrêté par event.cancelBubble=true (IE) ou event.stopPropagation() pour les autres navigateurs.

10voto

Adelin Points 4623

Il y a aussi le Event.eventPhase qui permet de savoir si l'événement se situe au niveau de la cible ou s'il provient d'un autre endroit, et elle est entièrement prise en charge par les navigateurs.

En développant le programme déjà excellent extrait de la réponse acceptée Voici le résultat obtenu en utilisant la méthode 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 votes

Document connexe de MDN sur composedPath et la limite d'ombre d'un élément DOM, est un contexte supplémentaire important.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X