Quelle est la différence entre un événement bouillonnant et une capture? Quand faut-il utiliser le bullage contre la capture?
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
.
<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>
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.
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.
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:
- 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.
- Tous les gestionnaires travaillant sur l'étape de formation de bulles excluent
addEventListener
avec le dernier argumenttrue
, qui est le seul moyen de capturer l'événement sur l'étape de capture.- Le bouillonnement/capture peut être arrêté avec
event.cancelBubble=true
(IE) ouevent.stopPropagation()
pour les autres navigateurs.
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>
_
Bubbling
Event propagate to the Upto root element is Bubbling.
Capture
Event propogate from body(root) element to eventTriggered Element is Capturing.