【问题标题】:How to check if some DOM element in another DOM element tree?如何检查某个 DOM 元素是否在另一个 DOM 元素树中?
【发布时间】:2014-09-30 20:55:19
【问题描述】:

如何检查某个 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>

所以只在&lt;div id='lvl1'&gt; 内点击更改&lt;div id="result"&gt; 区域。这是正确的解决方案(根据标准)吗?

那个 jQuery/Backbone/Underscore/Mojo/etc 都得这个?

【问题讨论】:

    标签: javascript dom javascript-events specifications


    【解决方案1】:

    我不会为此使用instanceof(尤其是因为它在 IE8 中不起作用,遗憾的是它会继续徘徊)。测试===要停止的节点,可能是document.bodydocument.documentElement&lt;html&gt;元素):

    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

    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 都得这个?

    对于您在上面所做的事情,jQuery 确实有两种方式:

    1. jQuery 支持event delegation,因此它会为您进行检查。但我不确定这是否适用于你正在做的事情。

    2. 如果由于某种原因你不能使用它,jQuery 的 closest 可能会有所帮助:

      if (!$(e.target).closest(".menu-area")[0]) {
          closeMenu();
      }
      

      closest 根据选择器测试元素,如果不匹配,则检查其父节点,依此类推。最后的[0] 告诉我们jQuery 是否发现了什么。在上面,如果它没有找到任何东西(开头的!),我们关闭菜单。

    【讨论】:

      猜你喜欢
      • 2018-11-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-04-01
      • 2014-11-14
      • 2013-11-09
      • 1970-01-01
      相关资源
      最近更新 更多