如何检查一些DOM元素是否在另一个DOM元素树中?
如何检查另一个DOM元素树中的某些DOM元素?
How to check if some DOM element in another DOM element tree?
例如,当您单击主页内容而不是菜单时,可以隐藏菜单: / p>
For example to hide menu when you click on main page content instead of menu you can:
document.addEventListener(function (e) {
var node = e.target;
do {
if (node.classList.contains('menu-area'))
return;
node = node.parentNode;
} while (node instanceof HTMLElement);
closeMenu();
});
请注意,当您点击非菜单区域时,通常的隐藏菜单的解决方案是 event.stopPropagation()
在菜单和非条件 document.addEventListener()
。
Note that usual solution to hide menu when you click to non-menu area is event.stopPropagation()
on menu and non-conditional document.addEventListener()
.
我通过 node = node.parentNode
和 ===
运算符:
<style>
div {
margin: 20px;
padding: 5px;
border: 1px green dotted;
}
</style>
<div id="lvl1">
<div id="lvl2">
<div id="lvl3">
Click me
</div>
</div>
</div>
<div id="result"></div>
<script>
var lvl1Node = document.getElementById('lvl1');
document.addEventListener('click', function(e) {
var node = e.target;
do {
if (lvl1Node === node) {
document.getElementById('result').innerHTML = "Event from: " + e.target.id;
return;
}
node = node.parentNode;
} while (node instanceof HTMLElement);
});
</script>
所以只需点击< div id ='lvl1'> / code>更改
< div id =result>
区域。那是正确的解决方案(根据标准)?
So only click inside <div id='lvl1'>
change <div id="result">
area. Is that right solution (according to standard)?
jQuery / Backbone / Underscore / Mojo / etc有这个吗?
That jQuery/Backbone/Underscore/Mojo/etc have to this?
我不会为此使用 instanceof
(尤其是因为它不会在IE8中工作,这可悲的是继续徘徊)测试 ===
您要停止的节点,可能 document.body
或 document.documentElement
(< html>
元素):
I wouldn't use instanceof
for this (not least because it won't work in IE8, which sadly continues to linger). Test for ===
the node where you want to stop, probably document.body
or document.documentElement
(the <html>
element):
document.addEventListener("click", function (e) {
var node = e.target;
do {
if (node.classList.contains('menu-area'))
return;
node = node.parentNode;
} while (node !== document.documentElement);
closeMenu();
});
或者您的循环具有初始化,测试和增量,这对 for
:
Or as your loop has initialization, test, and "increment," it's a good match for for
:
document.addEventListener("click", function (e) {
var node;
for (node = e.target; node !== document.documentElement; node = node.parentNode) {
if (node.classList.contains('menu-area')) {
return;
}
}
closeMenu();
});
那个jQuery / Backbone / Underscore / Mojo / etc有这个吗?
That jQuery/Backbone/Underscore/Mojo/etc have to this?
对于上面的操作,jQuery有两种方式:
For what you're doing above, jQuery does, yes, in two ways:
-
jQuery支持事件委托,因此它支票给你但是我不会马上确定这适用于你正在做的事情。
jQuery supports event delegation, so it does the checks for you. But I'm not immediately sure that applies to what you're doing.
如果由于某种原因你无法使用,jQuery的最接近
可能会帮助:
If for some reason you couldn't use that, jQuery's closest
would probably help:
if (!$(e.target).closest(".menu-area")[0]) {
closeMenu();
}
最接近
根据选择器测试元素,如果不匹配,则检查其父节点,依此类推。最后的 [0]
告诉我们jQuery是否找到任何东西。在上面,如果没有在开始时找到任何东西(!
),我们关闭菜单。
closest
tests the element against a selector and, if it doesn't match, checks its parent node, and so on. The [0]
at the end tells us whether jQuery found anything. In the above, if it didn't find anything (the !
at the beginning), we close the menu.