Javascript 确定 DOM 事件冒泡中的事件路径
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/26195091/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
determine event path in DOM Event bubbling
提问by Abhik
I am trying to find out the path through which an event has bubbled. For example , I have a mark up like
我试图找出事件冒泡的路径。例如,我有一个像
<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>
Now if btn2.3.1 was clicked, I wish to see the entire path the event has bubbled up through which is btn2.3.1 -> div2.3 -> div2 ->container . Is there a way of doing this with only putting a handler on the container ? (No Jquery please)
现在,如果单击 btn2.3.1,我希望看到事件冒泡的整个路径,即 btn2.3.1 -> div2.3 -> div2 ->container 。有没有办法只在容器上放置一个处理程序?(请不要使用 Jquery)
I found a event.path array.Which does this stuff, but couldn't find much details about it.Is it cross browser? What is the correct way to achieve this ?
我找到了一个 event.path 数组。这个东西是做什么的,但找不到关于它的很多细节。它是跨浏览器的吗?实现这一目标的正确方法是什么?
回答by Andrei Lesnitsky
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);
回答by Fred Gandt
event.path || event.composedPath()
event.path || event.composedPath()
event.path
event.path
Dis/Un-covered by a note in the polymer project documentationand via an HTML5Rocks article, pathis a family tree in the form of an Array.
通过在一份报告中DIS / UN-覆盖聚合物项目文档,并通过一个的HTML5Rocks文章,path是一个形式的家谱Array。
It appears to be an "extension to the eventinterface"only exposed via the Web ComponentShadow DOM, and is standardonly in this respect (apparently), not a lot of documentation seems available, and it isn't exposed (by default) in all browsers.
它似乎是仅通过Web Component Shadow DOM公开的“event接口扩展”,并且仅在这方面(显然)是标准的,似乎没有很多文档可用,并且它没有公开(默认情况下)所有浏览器。
event.composedPath()to the rescue!
event.composedPath()来救援!
Another question about the use of pathwas answered with a suggestion to use composedPath...
另一个关于使用的问题path得到了回答,建议使用composedPath...
MDN's documentation about event.composedPath()describes it as follows:
MDN的文档关于event.composedPath()它的描述如下:
The
composedPath()method of the Eventinterface returns the event's path which is an array of the objects on which listeners will be invoked. This does not include nodes in shadow trees if the shadow root was created with itsShadowRoot.modeclosed.
Event接口的
composedPath()方法返回事件的路径,该路径是将在其上调用侦听器的对象数组。如果影子根是在其关闭的情况下创建的,则这不包括影子树中的节点。ShadowRoot.mode
It is described by WHATWGin their "DOM specs" documentation about the "event path"as follows:
它是通过描述WHATWG在他们的“DOM规范”文件关于“活动路径”,如下所示:
Returns the invocation targetobjects of event'spath (objects on which listeners will be invoked), except for any nodesin shadow treesof which the shadow root's modeis "closed" that are not reachable from event's currentTarget.
回报调用目标的对象事件的路径(对象,听众将被调用),除了任何节点在阴影树木其中的阴影根的模式不是来自事件的到达是‘闭合’ currentTarget当前。
Can I use...states that browser support of composedPath()is widespread, with IE and Edge trailing behind with no foreseeable support, and MDN agrees.
Can I use...声明浏览器支持composedPath()广泛,IE 和 Edge 落后于没有可预见的支持,MDN 同意。
WHATWG's documentation about "dispatching events"details the conditions under which "event's path" will have items appended.
WHATWG 关于“调度事件”的文档详细说明了“事件path”将附加项目的条件。
Details correct September 25, 2019
详细信息更正 2019 年 9 月 25 日
Practical demo
实用演示
const green = document.getElementById( 'green' ),
msg = document.querySelector( 'output' );
document.getElementById( 'red' ).addEventListener( 'click', evt => {
msg.innerHTML = '"' + evt.target.id + '" got poked, and "green" was' +
/* access to the event path */
( ~evt.composedPath().indexOf( green ) ? '' : "<b>n't</b>" )
+ ' in the path.';
} );
div { display: inline-block; padding: 1em 3em 1em 1em; cursor: pointer }
output { font-family: monospace; display: block; margin-top: 1em }
#red { background: red }
#green { background: green }
#blue { background: blue }
<div id="red">
<div id="green">
<div id="blue"></div>
</div>
</div>
<output>Poke the DOM!</output>
回答by zbr
There is now a small GitHub project / NPM module called event-propagation-paththat acts as a polyfill. Check it out here:
现在有一个小的 GitHub 项目/NPM 模块称为event-propagation-pathpolyfill。在这里查看:
回答by Inamur Rahman
Let's assume that we what to find the event path inside the HTML table tag.
让我们假设我们要在 HTML table 标记中查找事件路径。
<tabe id="tab">
.
.
.
</table>
The following JavaScript code will return the event's element after every event.
以下 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;
}
回答by Rishabh Rajgarhia
I had a similar requirement where I was listening to event on document and wanted to know if the event originated in a particular div. I handled it by adding and later checking a specific class name on event.target.
我有一个类似的要求,我在听文档上的事件并想知道该事件是否起源于特定的 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>

