如何检查另一个DOM元素树中的某个DOM元素?
例如,当您点击主页内容而不是菜单时隐藏菜单,您可以:
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()
。
我使用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'>
更改<div id="result">
区域内部即可。这是正确的解决方案(根据标准)吗?
jQuery / Backbone / Underscore / Mojo /等有这个吗?
答案 0 :(得分:1)
我不会因此而使用instanceof
(尤其是因为它在IE8中无法工作,后者遗憾地继续存在)。测试===
您要停止的节点,可能是document.body
或document.documentElement
(<html>
元素):
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();
});
或者当你的循环有初始化,测试和&#34;增量时,&#34;它与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 /等有这个吗?
对于你上面所做的事情,jQuery有两种方式:
jQuery支持event delegation,因此它会为您进行检查。但我不能立即确定这适用于您正在做的事情。
如果出于某种原因你无法使用它,jQuery的closest
可能会有所帮助:
if (!$(e.target).closest(".menu-area")[0]) {
closeMenu();
}
closest
针对选择器测试元素,如果它不匹配,则检查其父节点,依此类推。最后的[0]
告诉我们jQuery是否发现了什么。在上面,如果没有找到任何内容(开头为!
),我们会关闭菜单。