No se puede entender el parámetro useCapture en addEventListener
Leí el artículo en https://developer.mozilla.org/en/DOM/element.addEventListener pero no puedo entender useCapture
el atributo. Definición hay:
Si es verdadero, useCapture indica que el usuario desea iniciar la captura. Después de iniciar la captura, todos los eventos del tipo especificado se enviarán al oyente registrado antes de enviarse a cualquier EventTarget debajo de él en el árbol DOM. Los eventos que se propagan hacia arriba a través del árbol no activarán un oyente designado para utilizar la captura.
En este código, el evento principal se activa antes que el secundario, por lo que no puedo entender su comportamiento. El objeto de documento tiene usecapture verdadero y el div secundario tiene usecapture establecido en falso y se sigue usecapture del documento. Entonces, ¿por qué se prefiere la propiedad del documento a la secundaria?
function load() {
document.addEventListener("click", function() {
alert("parent event");
}, true);
document.getElementById("div1").addEventListener("click", function() {
alert("child event");
}, false);
}
<body onload="load()">
<div id="div1">click me</div>
</body>
Los eventos se pueden activar en dos ocasiones: al principio ("captura") y al final ("burbuja"). Los eventos se ejecutan en el orden en que se definen. Digamos que defines 4 detectores de eventos:
window.addEventListener("click", function(){console.log(1)}, false);
window.addEventListener("click", function(){console.log(2)}, true);
window.addEventListener("click", function(){console.log(3)}, false);
window.addEventListener("click", function(){console.log(4)}, true);
Los mensajes de registro aparecerán en este orden:
2
(definido primero, usandocapture=true
)4
(definido segundo usandocapture=true
)1
(primer evento definido concapture=false
)3
(segundo evento definido concapture=false
)
Este diagrama me parece muy útil para comprender las fases de captura/objetivo/burbuja: http://www.w3.org/TR/2003/NOTE-DOM-Level-3-Events-20031107/events.html#Events-phases
A continuación, contenido extraído del enlace.
Etapas
El evento se envía siguiendo una ruta desde la raíz del árbol hasta este nodo de destino. Luego se puede manejar localmente en el nivel del nodo objetivo o desde los ancestros de cualquier objetivo que se encuentren más arriba en el árbol. El envío de eventos (también llamado propagación de eventos) ocurre en tres fases y en el siguiente orden:
- La fase de captura: el evento se envía a los antepasados del objetivo desde la raíz del árbol hasta el padre directo del nodo objetivo.
- La fase de destino: el evento se envía al nodo de destino.
- La fase de burbujeo: el evento se envía a los antepasados del objetivo desde el padre directo del nodo objetivo hasta la raíz del árbol.
Los antepasados del objetivo se determinan antes del envío inicial del evento. Si el nodo objetivo se elimina durante el envío, o se agrega o elimina un ancestro del objetivo, la propagación del evento siempre se basará en el nodo objetivo y los ancestros del objetivo determinados antes del envío.
Es posible que algunos eventos no cumplan necesariamente las tres fases del flujo de eventos DOM; por ejemplo, el evento solo podría definirse para una o dos fases. Como ejemplo, los eventos definidos en esta especificación siempre cumplirán las fases de captura y destino, pero algunos no cumplirán la fase de burbujeo ("eventos burbujeantes" versus "eventos no burbujeantes", consulte también el atributo Event.bubbles).
Captura de evento ( useCapture = true
) frente a evento de burbuja ( useCapture = false
)
Referencia de MDN
- El evento de captura se enviará antes del evento de burbuja
- El orden de propagación de eventos es
- Captura de padres
- Captura de niños
- Captura de objetivo y burbuja de objetivo
- En el orden en que fueron registrados.
- Cuando el elemento es el objetivo del evento,
useCapture
el parámetro no importa (Gracias @bam y @legend80s)
- Burbuja de niños
- Burbuja para padres
stopPropagation()
detendrá el flujo
Manifestación
Resultado:
Captura de padres
Burbuja objetivo 1
(Debido a que Capture y Bubble of Target se activarán en el orden en que fueron registrados, este se activa primero)
Captura de objetivos
Burbuja objetivo 2
Burbuja para padres
var parent = document.getElementById('parent');
var target = document.getElementById('target');
// "target" will trigger in the order of register (addEventListener()), capture / bubble don't affect the order
// #2
target.addEventListener('click', function (e) {
console.log('Target Bubble 1');
// e.stopPropagation();
}, false);
// #3
target.addEventListener('click', function (e) {
console.log('Target Capture');
// e.stopPropagation();
}, true);
// #4
target.addEventListener('click', function (e) {
console.log('Target Bubble 2');
// e.stopPropagation();
}, false);
// #1 : "parent capture" first
parent.addEventListener('click', function (e) {
console.log('Parent Capture');
// e.stopPropagation();
}, true);
// #5 : "parent bubble" last
parent.addEventListener('click', function (e) {
console.log('Parent Bubble');
// e.stopPropagation();
}, false);
<div id="parent">
<button id="target" style="padding: 1em 0.8em;">
Trigger event
</button>
</div>
Cuando dices useCapture = true, los eventos se ejecutan de arriba a abajo en la fase de captura; cuando es false, hace una burbuja de abajo hacia arriba.