Unable to understand useCapture parameter in addEventListener
I find this diagram is very useful for understanding the capture/target/bubble phases: http://www.w3.org/TR/2003/NOTE-DOM-Level-3-Events-20031107/events.html#Events-phases
Below, content extracted from the link.
Phases
The event is dispatched following a path from the root of the tree to this target node. It can then be handled locally at the target node level or from any target's ancestors higher in the tree. The event dispatching (also called event propagation) occurs in three phases and the following order:
- The capture phase: the event is dispatched to the target's ancestors from the root of the tree to the direct parent of the target node.
- The target phase: the event is dispatched to the target node.
- The bubbling phase: the event is dispatched to the target's ancestors from the direct parent of the target node to the root of the tree.
The target's ancestors are determined before the initial dispatch of the event. If the target node is removed during the dispatching, or a target's ancestor is added or removed, the event propagation will always be based on the target node and the target's ancestors determined before the dispatch.
Some events may not necessarily accomplish the three phases of the DOM event flow, e.g. the event could only be defined for one or two phases. As an example, events defined in this specification will always accomplish the capture and target phases but some will not accomplish the bubbling phase ("bubbling events" versus "non-bubbling events", see also the Event.bubbles attribute).
Capture Event (useCapture = true
) vs Bubble Event (useCapture = false
)
MDN Reference
- Capture Event will be dispatch before Bubble Event
- Event propagation order is
- Parent Capture
- Children Capture
- Target Capture and Target Bubble
- In the order they were registered
- When the element is the target of the event,
useCapture
parameter doesn't matter (Thanks @bam and @legend80s)
- Children Bubble
- Parent Bubble
stopPropagation()
will stop the flow
Demo
Result:
- Parent Capture
Target Bubble 1
(Because Capture and Bubble of Target will trigger in the order they were registered, so Bubble event is trigger before Capture event)
Target Capture
- Target Bubble 2
- Parent Bubble
var parent = document.getElementById('parent'),
target = document.getElementById('target');
target.addEventListener('click', function (e) {
console.log('Target Bubble 1');
// e.stopPropagation();
}, false);
target.addEventListener('click', function (e) {
console.log('Target Capture');
// e.stopPropagation();
}, true);
target.addEventListener('click', function (e) {
console.log('Target Bubble 2');
// e.stopPropagation();
}, false);
parent.addEventListener('click', function (e) {
console.log('Parent Capture');
// e.stopPropagation();
}, true);
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>
Events can be activated at two occasions: At the beginning ("capture"), and at the end ("bubble"). Events are executed in the order of how they're defined. Say, you define 4 event listeners:
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);
The log messages will appear in this order:
2
(defined first, usingcapture=true
)4
(defined second usingcapture=true
)1
(first defined event withcapture=false
)3
(second defined event withcapture=false
)
When you say useCapture = true the Events execute top to down in the capture phase when false it does a bubble bottom to top.