Event capturing
Event capturing is the phase in which a DOM event travels from outer ancestors toward its target. Register a listener with `{ capture: true }` to handle the event on that inward path, before it reaches the target.
Event capturing is the phase in DOM event propagation where an event travels from the outermost relevant ancestors toward its target. For a click on a button nested inside a `div`, capture listeners on `body` and then the `div` run before the event reaches the button.
Register a listener for this phase with `addEventListener(type, listener, { capture: true })`; omitting `capture` (or setting it to `false`) registers for the bubbling phase. At the target, listeners registered for the target phase are invoked. If the event bubbles, it then travels back through ancestors in reverse order.
The `event.target` identifies the originating target, while `event.currentTarget` identifies the object whose listener is currently running. `event.eventPhase` reports the current phase, such as `Event.CAPTURING_PHASE` or `Event.AT_TARGET`.
Capturing can be useful when an ancestor needs to observe or handle an event before descendant handlers run. Propagation can be stopped with `stopPropagation()`, but that prevents further traversal and should be used deliberately. Event delegation is commonly implemented with bubbling, though capture can serve similar ancestor-listening needs.
Key points
- Capture listeners run on ancestors on the path toward the event target.
- Use `{ capture: true }` in `addEventListener()` to register a capture-phase listener.
- At-target handling follows capture; bubbling, when enabled, then travels back toward ancestors.
- Use `target` for the origin and `currentTarget` for the object handling the current listener.
Interview questions
What is event capturing in the DOM?
Capture is the phase in which an event moves from the outer ancestors toward the target. A listener must be registered with the `capture` option set to `true` to run during that phase. After capture, listeners at the target run; if the event bubbles, ancestor listeners can run on the return path.
What is the listener order for a click on a nested button with capture listeners on `body` and its parent?
For an event originating on the button, capture listeners run first on `body`, then on the containing `div`. The button is then reached at the target phase, where its listener runs. If bubbling is enabled and listeners exist, propagation then proceeds from the button's parent outward.
How do `event.target` and `event.currentTarget` differ?
`target` is the event's originating object, and it remains the origin as the event propagates. `currentTarget` is the object whose listener is executing, so it differs as the event visits different listeners. This distinction is important for ancestor handlers and event delegation.
What does `stopPropagation()` do, and how does it differ from `preventDefault()`?
Calling `stopPropagation()` prevents the event from continuing to other objects along its propagation path. It does not cancel the browser's default action, such as a link navigation; `preventDefault()` is used for that when the event is cancelable. Stopping propagation does not generally prevent other listeners on the same object from running; `stopImmediatePropagation()` is the stronger option.