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

问题描述 投票:10回答:3

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

 <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 - > div2.3 - > div2 - > container。有没有办法只在容器上放一个处理程序? (请不要Jquery)

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

javascript html dom
3个回答
16
投票

event.path || event.composedPath()

event.path

来自whatwg

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

polymer project documentationan HTML5Rocks article中的音符消息/未被覆盖,这似乎是仅通过event Shadow DOM暴露的“Web Component界面的扩展”。

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

自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>

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);

0
投票

现在有一个名为event-propagation-path的小型GitHub项目/ NPM模块,它充当了polyfill。看看这里:

event-propagation-path @ GitHub

event-propagation-path @ NPM

© www.soinside.com 2019 - 2024. All rights reserved.