You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: 2-ui/2-events/02-bubbling-and-capturing/article.md
+20-10Lines changed: 20 additions & 10 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -130,7 +130,7 @@ Here's the picture of a click on `<td>` inside a table, taken from the specifica
130
130
131
131

132
132
133
-
That is: for a click on `<td>` the event first goes through the ancestors chain down to the element (capturing), then it reaches the target, and then it goes up (bubbles), calling handlers on its way.
133
+
That is: for a click on `<td>` the event first goes through the ancestors chain down to the element (capturing phase), then it reaches the target and triggers there (target phase), and then it goes up (bubbling phase), calling handlers on its way.
134
134
135
135
**Before we only talked about bubbling, because the capturing phase is rarely used. Normally it is invisible to us.**
136
136
@@ -149,6 +149,7 @@ There are two possible values of the `capture` option:
149
149
- If it's `false` (default), then the handler is set on the bubbling phase.
150
150
- If it's `true`, then the handler is set on the capturing phase.
151
151
152
+
152
153
Note that while formally there are 3 phases, the 2nd phase ("target phase": the event reached the element) is not handled separately: handlers on both capturing and bubbling phases trigger at that phase.
153
154
154
155
Let's see both capturing and bubbling in action:
@@ -179,30 +180,39 @@ The code sets click handlers on *every* element in the document to see which one
179
180
180
181
If you click on `<p>`, then the sequence is:
181
182
182
-
1.`HTML` -> `BODY` -> `FORM` -> `DIV` -> `P` (capturing phase, the first listener), and then:
183
-
2.`P` -> `DIV` -> `FORM` -> `BODY` -> `HTML` (bubbling phase, the second listener).
184
-
185
-
Please note that `P` shows up two times: at the end of capturing and at the start of bubbling.
183
+
1.`HTML` -> `BODY` -> `FORM` -> `DIV` (capturing phase, the first listener):
184
+
2.`P` (target phrase, triggers two times, as there are both capturing and bubbling listeners)
185
+
3.`DIV` -> `FORM` -> `BODY` -> `HTML` (bubbling phase, the second listener).
186
186
187
187
There's a property `event.eventPhase` that tells us the number of the phase on which the event was caught. But it's rarely used, because we usually know it in the handler.
188
188
189
189
```smart header="To remove the handler, `removeEventListener` needs the same phase"
190
190
If we `addEventListener(..., true)`, then we should mention the same phase in `removeEventListener(..., true)` to correctly remove the handler.
191
191
```
192
192
193
+
````smart header="Listeners on same element and same phase run in their set order"
194
+
If we have multiple event handlers on the same phase, assigned to the same element with `addEventListener`, they run in the same order as they are created:
195
+
196
+
```js
197
+
elem.addEventListener("click", e => alert(1)); // guaranteed to trigger first
198
+
elem.addEventListener("click", e => alert(2));
199
+
```
200
+
````
201
+
202
+
193
203
## Summary
194
204
195
-
The event handling process:
205
+
When an event happens -- the most nested element where it happens gets labeled as the "target element" (`event.target`).
196
206
197
-
- When an event happens -- the most nested element where it happens gets labeled as the "target element" (`event.target`).
198
-
- Then the event first moves from the document root down to the `event.target`, calling handlers assigned with `addEventListener(...., true)` on the way (`true` is a shorthand for `{capture: true}`).
199
-
- Then the event moves from `event.target` up to the root, calling handlers assigned using `on<event>` and `addEventListener` without the 3rd argument or with the 3rd argument `false`.
207
+
- Then the event moves down from the document root to `event.target`, calling handlers assigned with `addEventListener(...., true)` on the way (`true` is a shorthand for `{capture: true}`).
208
+
- Then handlers are called on the target element itself.
209
+
- Then the event bubbles up from `event.target` up to the root, calling handlers assigned using `on<event>` and `addEventListener` without the 3rd argument or with the 3rd argument `false/{capture:false}`.
200
210
201
211
Each handler can access `event` object properties:
202
212
203
213
- `event.target` -- the deepest element that originated the event.
204
214
- `event.currentTarget` (=`this`) -- the current element that handles the event (the one that has the handler on it)
205
-
- `event.eventPhase` -- the current phase (capturing=1, bubbling=3).
215
+
- `event.eventPhase` -- the current phase (capturing=1, target=2, bubbling=3).
206
216
207
217
Any event handler can stop the event by calling `event.stopPropagation()`, but that's not recommended, because we can't really be sure we won't need it above, maybe for completely different things.
0 commit comments