Why doesn't event bubbling work in detached DOM elements?

烈酒焚心 提交于 2021-01-27 05:11:07

问题


I have a parent <div> with one child <div> in memory - not attached to the current document. I want to trigger a CustomEvent on the child but listen to that event from the parent. Here is my code:

var parent = document.createElement('div');
var child = document.createElement('div');
parent.appendChild(child);
parent.addEventListener('boom', function(event) {
    console.log('parent listener', event); // <~ This never runs!
});
var event = new CustomEvent('boom', { bubbles: true });
child.dispatchEvent(event);

This code doesn't work as expected. The event listener on the parent never fires. This seems to be a contradiction of the JavaScript event system whereby events bubble up from the target. However, if I modify the final two lines of this snippet to the following, the callback fires as I would expect it to:

document.body.appendChild(parent);
child.dispatchEvent(event);

In other words, if I append my fragment as a subtree of the document before dispatching the event, then the parent event listener fires exactly as expected. Why? Is there a way to allow bubbling when using detached DOM elements?


回答1:


Why [doesn't bubbling work on detached elements]?

To answer your first question, I looked at the W3C "UI Events (formerly DOM Level 3 Events)" spec, and didn't see anything that addressed this issue specifically. However, the event phase portion mentions a few things that makes this behavior seem reasonable.

As the next step, the event object must complete one or more event phases. This specification defines three event phases: capture phase, target phase and bubble phase. Event objects complete these phases in the specified order using the partial propagation paths as defined below. A phase must be skipped if it is not supported, or if the event object's propagation has been stopped. For example, if the Event.bubbles attribute is set to false, the bubble phase will be skipped, and if Event.stopPropagation() has been called prior to the dispatch, all phases must be skipped.

Emphasis mine.

The spec then goes on to list the phases:

  1. The capture phase: The event object must propagate through the target's ancestors from the Window to the target's parent. This phase is also known as the capturing phase. Event listeners registered for this phase must handle the event before it reaches its target.
  2. The target phase: The event object must arrive at the event object's event target. This phase is also known as the at-target phase. Event listeners registered for this phase must handle the event once it has reached its target. If the event type indicates that the event must not bubble, the event object must halt after completion of this phase.
  3. The bubble phase: The event object propagates through the target's ancestors in reverse order, starting with the target's parent and ending with the Window. This phase is also known as the bubbling phase. Event listeners registered for this phase must handle the event after it has reached its target.

Again, emphasis mine. The spec never calls out what happens with detached elements explicitly. Given that the target and bubble phases require the path to go from the element to the window, and that no path is possible on detached elements, it follows that the target and bubble event phases must be skipped because those paths are not supported.

Is there a way to allow bubbling when using detached DOM elements?

As far as I can tell, there's nothing built-in that would allow bubbling. You might be able to fake bubbling with some custom code, but that would require checking whether the element is detached every time you trigger an event.

Another thought would be to add the elements to the DOM, trigger the event, and detach the elements. As I haven't tested this, I have no idea whether it would work.



来源:https://stackoverflow.com/questions/29583766/why-doesnt-event-bubbling-work-in-detached-dom-elements

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!