我有一个父<div>
,内存中有一个子<div>
- 未附加到当前文档。我想在孩子身上触发一个CustomEvent
但是从父母那里听那个事件。这是我的代码:
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);
此代码无法按预期工作。父节点上的事件侦听器永远不会触发。这似乎与JavaScript事件系统相矛盾,因为事件从目标中冒出来。但是,如果我将此代码段的最后两行修改为以下内容,则回调将按照我的预期触发:
document.body.appendChild(parent);
child.dispatchEvent(event);
换句话说,如果我在调度事件之前将我的片段作为文档的子树附加,那么父事件侦听器将按预期完全触发。为什么?有没有办法在使用分离的DOM元素时允许冒泡?
答案 0 :(得分:4)
为什么[没有冒泡在分离的元素上工作]?
要回答您的第一个问题,我查看了W3C "UI Events (formerly DOM Level 3 Events)" spec,并没有看到任何具体解决此问题的内容。但是,event phase部分提到了一些使这种行为看似合理的事情。
作为下一步,事件对象必须完成一个或多个事件阶段。该规范定义了三个事件阶段:捕获阶段,目标阶段和泡沫阶段。事件对象使用下面定义的部分传播路径以指定的顺序完成这些阶段。 如果不支持,则必须跳过某个阶段,或者如果事件对象的传播已停止,则必须跳过该阶段。例如,如果Event.bubbles属性设置为false,则将跳过冒泡阶段,如果在分派之前调用了Event.stopPropagation(),则必须跳过所有阶段。
强调我的。
然后规范继续列出阶段:
- 捕获阶段:事件对象必须通过目标的祖先从Window传播到目标的父级。该阶段也称为捕获阶段。在此阶段注册的事件侦听器必须在事件到达其目标之前处理该事件。
- 目标阶段:事件对象必须到达事件对象的事件目标。该阶段也称为目标阶段。为此阶段注册的事件侦听器必须在事件达到其目标后处理该事件。如果事件类型指示事件不得冒泡,则事件对象必须在此阶段完成后停止。
- 气泡阶段:事件对象以相反的顺序传播到目标的祖先,从目标的父级开始,以Window结尾。该阶段也称为起泡阶段。在此阶段注册的事件侦听器必须在事件达到其目标后处理该事件。
醇>
再一次,强调我的。规范永远不会明确地指出分离元素会发生什么。鉴于目标和泡泡阶段需要从元素到窗口的路径,并且在分离的元素上没有路径,因此必须跳过目标和气泡事件阶段,因为不支持这些路径。
使用分离的DOM元素时是否有允许冒泡的方法?
据我所知,没有任何内置可以冒泡。您可以使用一些自定义代码伪装冒泡,但这需要在每次触发事件时检查元素是否已分离。
另一种想法是将元素添加到DOM,触发事件并分离元素。由于我没有对此进行测试,我不知道它是否会起作用。