确定DOM事件冒泡中的事件路径

时间:2014-10-04 17:07:34

标签: javascript html dom

我试图找出事件冒泡的路径。例如,我有一个像

的标记
 <div id="container" onclick="func">
        <div id="div1"></div>
        <div id="div2">
            <div id="div2.1"></div>
            <span id="span2.2"></span>
            <div id="div2.3">
                <button id="btn2.3.1"></button>
            </div>
        </div>
    </div>

现在如果单击btn2.3.1,我希望看到事件已经冒出的整个路径,其中btn2.3.1 - &gt; div2.3 - &gt; div2 - &gt;容器。有没有办法只在容器上放一个处理程序? (请不要Jquery)

我找到了一个event.path数组。这是什么东西,但是找不到它的详细信息。它是否跨浏览器?实现这一目标的正确方法是什么?

5 个答案:

答案 0 :(得分:20)

function handleClicks(e) {
    var path = [];
    var node = e.target;
    while(node != document.body) {
       path.push(node);
       node = node.parentNode;
    }
    console.log(path);
}

document.body.addEventListener('click', handleClicks);

答案 1 :(得分:15)

event.path || event.composedPath()

event.path

来自whatwg

  

如果事件的目标属性值参与树,则让事件路径成为树序中所有祖先的静态有序列表,否则让事件路径成为空列表。

通过polymer project documentationan HTML5Rocks article中的备注拒绝/取消覆盖,这似乎只是event界面的“扩展名通过Web Component Shadow DOM 曝光。

标准仅在这方面(显然),虽然现在还没有很多文档可用(我们必须写它; - )

自2016年1月23日起,所有浏览器均未公开(默认情况下)。

但基本上是:

var red = document.getElementById( "red" ),
    green = document.getElementById( "green" ),
    msg = document.querySelector( "p" );

red.addEventListener( "click", function( evt ) {
    msg.textContent = "'" + evt.target.id + "' got poked, and 'green' was" +
    
    // access to the event path
    ( ~evt.path.indexOf( green ) ? "" : "n't" ) +
    
    " in the path.";
}, false );
div { display: inline-block; min-width: 20px; min-height: 20px;
      padding: 20px 40px 20px 20px; text-align: center; cursor: pointer; }
#red { background: red; }
#green { background: green; }
#blue { background: blue; }
p { font: 20px Consolas; }
<!DOCTYPE html><html><body>
    <div id="red">
        <div id="green">
            <div id="blue"></div>
        </div>
    </div>
    <p></p>
</body></html>

换句话说:path是一个Array形式的家谱。

另一个question about the use of pathanswered with a suggestion to use composedPath ...

event.composedPath()

自从我上次编辑此答案以来,MDN已经发展(双关语)some documentation about event.composedPath()

截至2019年3月8日,根据MDN,Edge或IE不支持此功能。

注意事项照常应用:

  

如果阴影根是在ShadowRoot.mode关闭的情况下创建的,那么[将在其上调用侦听器的对象数组]不包括阴影树中的节点。

上面的相同的代码段使用composedPath()看起来和这样工作:

var red = document.getElementById( "red" ),
    green = document.getElementById( "green" ),
    msg = document.querySelector( "p" );

red.addEventListener( "click", function( evt ) {
    msg.textContent = "'" + evt.target.id + "' got poked, and 'green' was" +
    
    // access to the event path
    ( ~evt.composedPath().indexOf( green ) ? "" : "n't" ) +
    
    " in the path.";
}, false );
div { display: inline-block; min-width: 20px; min-height: 20px;
      padding: 20px 40px 20px 20px; text-align: center; cursor: pointer; }
#red { background: red; }
#green { background: green; }
#blue { background: blue; }
p { font: 20px Consolas; }
<!DOCTYPE html><html><body>
    <div id="red">
        <div id="green">
            <div id="blue"></div>
        </div>
    </div>
    <p></p>
</body></html>

答案 2 :(得分:1)

我在听文档上的事件时有一个类似的要求,想知道事件是否起源于特定的div。我通过添加并稍后检查event.target上的特定类名称来处理它。

var div1 = document.getElementById('div1');
var div2 = document.getElementById('div2');

document.addEventListener('click', function(e) {
  if (e.target.classList.contains('via-div1')) {
    alert('Event came through div1');
  } else if (e.target.classList.contains('via-div2')) {
    alert('Event came through div2');
  } else {
    alert('Event came from outside the divs');
  }
});

div1.addEventListener('click', function(e) {
  e.target.classList.add('via-div1');
});

div2.addEventListener('click', function(e) {
  e.target.classList.add('via-div2');
});
<div id="div1" style="background: #8bc34a"><span>div 1</span></div>
<div id="div2" style="background: #00bcd4">
  <span>div 2</span>
  <div id="div2-1"><span>div 2-1</span></div>
  <button id="btn2-2">button 2-2</button>
</div>

答案 3 :(得分:0)

现在有一个名为.ToList的小型GitHub项目/ NPM模块充当了polyfill。在这里查看:

event-propagation-path @ GitHub

event-propagation-path @ NPM

答案 4 :(得分:0)

让我们假设我们要在HTML table标记内找到事件路径。

<tabe id="tab">
.
.
.
</table>

以下JavaScript代码将在每个事件之后返回事件的元素。

window.onload = function(){
var tab = document.getElementById('tab');
tab.onclick = function(event) {
var target = getTargetElement(event);
console.log(target);
};
}
function getTargetElement(e) {
e = e || window.event;
return e.target || e.srcElement;
}