ChatGPT解决这个技术问题 Extra ChatGPT

What is event bubbling and capturing?

What is the difference between event bubbling and capturing? When should one use bubbling vs capturing?

I recommend this useful link: javascript.info/bubbling-and-capturing
@CommunityAns: this site is excellent, but this topic, particularly, is depicted in a somewhat confusing way.
Needing engineers to be aware of the difference of both, and have code that can be broken simply by choosing an "incorrect" propagation type, is in my opinion a code-smell (or anti-pattern). A better way to go about it is to just enforce a coding style where propagation type doesn't matter.

s
subject-q

Event bubbling and capturing are two ways of event propagation in the HTML DOM API, when an event occurs in an element inside another element, and both elements have registered a handle for that event. The event propagation mode determines in which order the elements receive the event.

With bubbling, the event is first captured and handled by the innermost element and then propagated to outer elements.

With capturing, the event is first captured by the outermost element and propagated to the inner elements.

Capturing is also called "trickling", which helps remember the propagation order:

trickle down, bubble up

Back in the old days, Netscape advocated event capturing, while Microsoft promoted event bubbling. Both are part of the W3C Document Object Model Events standard (2000).

IE < 9 uses only event bubbling, whereas IE9+ and all major browsers support both. On the other hand, the performance of event bubbling may be slightly lower for complex DOMs.

We can use the addEventListener(type, listener, useCapture) to register event handlers for in either bubbling (default) or capturing mode. To use the capturing model pass the third argument as true.

Example

<div>
    <ul>
        <li></li>
    </ul>
</div>

In the structure above, assume that a click event occurred in the li element.

In capturing model, the event will be handled by the div first (click event handlers in the div will fire first), then in the ul, then at the last in the target element, li.

In the bubbling model, the opposite will happen: the event will be first handled by the li, then by the ul, and at last by the div element.

For more information, see

Event Order on QuirksMode

addEventListener on MDN

Events Advanced on QuirksMode

In the example below, if you click on any of the highlighted elements, you can see that the capturing phase of the event propagation flow occurs first, followed by the bubbling phase.

var logElement = document.getElementById('log'); function log(msg) { logElement.innerHTML += ('

' + msg + '

'); } 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; }
1
2
3
4
5

Another example at JSFiddle.


useCapture now supported in IE >= 9. source
I know its too late to put comment but nice article i found here catcode.com/domcontent/events/capture.html
Is triclkling the same as capturing? Crockford talks about Trickling v. Bubbling in this video talk - youtube.com/watch?v=Fv9qT9joc0M&list=PL7664379246A246CB around 1 hr 5 minutes.
The answer above correct in regards to the order in the detailed explanation, but leaves you thinking that trickle occurs second with "bubble up, trickle down". Events always go through the capture phase before the bubble phase. The correct order is trickle down => onElement => bubble up
"With bubbling, the event is first captured and handled by the innermost element and then propagated to outer elements." -- You should point out that not all events bubble (e.g., focus).
F
Felix Kling

Description:

quirksmode.org has a nice description of this. In a nutshell (copied from quirksmode):

Event capturing When you use event capturing | | ---------------| |----------------- | element1 | | | | -----------| |----------- | | |element2 \ / | | | ------------------------- | | Event CAPTURING | ----------------------------------- the event handler of element1 fires first, the event handler of element2 fires last. Event bubbling When you use event bubbling / \ ---------------| |----------------- | element1 | | | | -----------| |----------- | | |element2 | | | | | ------------------------- | | Event BUBBLING | ----------------------------------- the event handler of element2 fires first, the event handler of element1 fires last.

What to use?

It depends on what you want to do. There is no better. The difference is the order of the execution of the event handlers. Most of the time it will be fine to fire event handlers in the bubbling phase but it can also be necessary to fire them earlier.


Does not both happens, first capturing and then bubbling, also what is dispatch event?
a graphical example is here: javascript.info/bubbling-and-capturing
Capture phase handlers are particularly useful when some element's code (code you don't control, like a plugin) is stopping propagation, and you really want to know when that event occurs. You can pick it up on the way to them instead of on the way back. You might not get it in the bubbling phase if they stopped its propagation.
d
dinesh_malhotra

If there are two elements element 1 and element 2. Element 2 is inside element 1 and we attach an event handler with both the elements lets say onClick. Now when we click on element 2 then eventHandler for both the elements will be executed. Now here the question is in which order the event will execute. If the event attached with element 1 executes first it is called event capturing and if the event attached with element 2 executes first this is called event bubbling. As per W3C the event will start in the capturing phase until it reaches the target comes back to the element and then it starts bubbling

The capturing and bubbling states are known by the useCapture parameter of addEventListener method

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

By Default useCapture is false. It means it is in the bubbling phase.

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 1
div 2

Please try with changing true and false.


@masterxilo: no need for Fiddle, StackOverflow now supports inline code (stack snippets).
Regarding the event will start in the capturing phase untill it reaches the target comes back to the element and then it starts bubbling. I only found the addEventListener has the parameter useCapture which can be set to true or false; and in HTML 4.0, event listeners were specified as attributes of an element and useCapture defaults to false. Could you link to a spec that confirms what you wrote?
M
MarredCheese

I have found this tutorial at javascript.info to be very clear in explaining this topic. And its 3-points summary at the end is really talking to the crucial points. I quote it here:

Events first are captured down to deepest target, then bubble up. In IE<9 they only bubble. All handlers work on bubbling stage excepts addEventListener with last argument true, which is the only way to catch the event on capturing stage. Bubbling/capturing can be stopped by event.cancelBubble=true (IE) or event.stopPropagation() for other browsers.


A
Adelin

There's also the Event.eventPhase property which can tell you if the event is at target or comes from somewhere else, and it is fully supported by browsers.

Expanding on the already great snippet from the accepted answer, this is the output using the eventPhase property

var logElement = document.getElementById('log'); function log(msg) { if (logElement.innerHTML == "

No logs

") logElement.innerHTML = ""; logElement.innerHTML += ('

' + msg + '

'); } 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; }
1
2
3
4
5


MDN's related doc on composedPath, and the shadow-boundary for a DOM element, is great additional context
v
vitoboski

DOM Events describes 3 phases of event propagation: Capturing phase – the event goes down to the element. Target phase – the event reached the target element. Bubbling phase – the event bubbles up from the element.

https://i.stack.imgur.com/LsIr2.png


K
Kondal

Bubbling

  Event propagate to the upto root element is **BUBBLING**.

Capturing

  Event propagate from body(root) element to eventTriggered Element is **CAPTURING**.

h
horcrux

As other said, bubbling and capturing describe in which order some nested elements receive a given event.

I wanted to point out that for the innermost element may appear something strange. Indeed, in this case the order in which the event listeners are added does matter.

In the following example, capturing for div2 will be executed first than bubbling; while bubbling for div4 will be executed first than capturing.

function addClickListener (msg, num, type) { document.querySelector("#div" + num) .addEventListener("click", () => alert(msg + num), type); } bubble = (num) => addClickListener("bubble ", num, false); capture = (num) => addClickListener("capture ", num, true); // first capture then bubble capture(1); capture(2); bubble(2); bubble(1); // try reverse order bubble(3); bubble(4); capture(4); capture(3); #div1, #div2, #div3, #div4 { border: solid 1px; padding: 3px; margin: 3px; }

div 1
div 2
div 3
div 4

EDIT: Such behavior may vary according to the browser (e.g. currently occurs on Firefox, but not on Chrome and Edge). Nevertheless, I think one should be aware of it.


The order of adding the event listeners does not matter try you own example if still not sure.
@sasidhar My example is self explanatory. Now if you click on the div #4 you get "capture 3, bubble 4, capture 4, bubble 3". If you reverse the order asserting capture(3); capture(4); bubble(4); bubble(3); and then click again on div #4 you'd get instead "capture 3, capture 4, bubble 4, bubble 3". This is a fact, even though I wouldn't be able to explain it.
tried your example in Edge and chrome, irrespective of order the result is always capture(3); capture(4); bubble(4); bubble(3)'
@sasidhar Sorry for the late reply. I use Firefox, anyway.