为什么事件冒泡在分离的DOM元素中不起作用?

时间:2015-04-11 22:24:47

标签: javascript google-chrome dom javascript-events

我有一个父<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元素时允许冒泡?

1 个答案:

答案 0 :(得分:4)

  

为什么[没有冒泡在分离的元素上工作]?

要回答您的第一个问题,我查看了W3C "UI Events (formerly DOM Level 3 Events)" spec,并没有看到任何具体解决此问题的内容。但是,event phase部分提到了一些使这种行为看似合理的事情。

  

作为下一步,事件对象必须完成一个或多个事件阶段。该规范定义了三个事件阶段:捕获阶段,目标阶段和泡沫阶段。事件对象使用下面定义的部分传播路径以指定的顺序完成这些阶段。 如果不支持,则必须跳过某个阶段,或者如果事件对象的传播已停止,则必须跳过该阶段。例如,如果Event.bubbles属性设置为false,则将跳过冒泡阶段,如果在分派之前调用了Event.stopPropagation(),则必须跳过所有阶段。

强调我的。

然后规范继续列出阶段:

  
      
  1. 捕获阶段事件对象必须通过目标的祖先从Window传播到目标的父级。该阶段也称为捕获阶段。在此阶段注册的事件侦听器必须在事件到达其目标之前处理该事件。
  2.   
  3. 目标阶段:事件对象必须到达事件对象的事件目标。该阶段也称为目标阶段。为此阶段注册的事件侦听器必须在事件达到其目标后处理该事件。如果事件类型指示事件不得冒泡,则事件对象必须在此阶段完成后停止。
  4.   
  5. 气泡阶段事件对象以相反的顺序传播到目标的祖先,从目标的父级开始,以Window结尾。该阶段也称为起泡阶段。在此阶段注册的事件侦听器必须在事件达到其目标后处理该事件。
  6.   

再一次,强调我的。规范永远不会明确地指出分离元素会发生什么。鉴于目标和泡泡阶段需要从元素到窗口的路径,并且在分离的元素上没有路径,因此必须跳过目标和气泡事件阶段,因为不支持这些路径。

  

使用分离的DOM元素时是否有允许冒泡的方法?

据我所知,没有任何内置可以冒泡。您可以使用一些自定义代码伪装冒泡,但这需要在每次触发事件时检查元素是否已分离。

另一种想法是将元素添加到DOM,触发事件并分离元素。由于我没有对此进行测试,我不知道它是否会起作用。

相关问题