【问题标题】:Event Propagation With One Event Listener And Nested Children使用一个事件侦听器和嵌套子级进行事件传播
【发布时间】:2022-01-14 11:28:22
【问题描述】:

在我的网站上,我有一些带有一些内容的 div 元素。每个元素都应该是可点击的。我可以为每个事件添加一个单独的事件侦听器,但我宁愿将一个事件侦听器附加到容器。为了更好地解释文档结构,我在下面添加了一个示例。

<div id="container">
  <div>
    <h1>Element 1</h1>
    <p>Lorem ipsum...</p>
  </div>
  <div>
    <h1>Element 2</h1>
    <p>...dolor sit amet...</p>
  </div>
</div>

现在我的问题如下:我知道使用 event.target 可以让我获得已点击的实际元素,当使用一个附加到 div 且 ID 为 container 的事件侦听器时 - 可以是容器、直接子元素之一或其中的文本元素。如何确定用户点击了哪些内部 div 元素(如果有),即使目标不是 div 本身?

如果有使用 JQuery 的不同/更简单的解决方案,我也会对此感兴趣。

【问题讨论】:

  • 鉴于您知道event.target 为您提供了对被点击元素的引用...这似乎已经回答了您的问题?这也是“jQuery”的做法。请注意,还有event.currentTarget 属性,在委托事件处理程序中,它始终是事件被分配到的父元素,而不是引发事件的元素。
  • 为共同祖先(内部 div 元素")div 提供可识别的类,然后检查event.target.closest('.recognizable-class') 是否存在。如果存在,它也是您想要的 div得到。
  • @RoryMcCrossan 是否有比测试目标是否为div 并在不是时使用父元素更简单的方法? event.currentTarget 的信息很有帮助。
  • @Teemu 我不能只使用closest() 函数来获取下一个div 元素,然后检查它是否具有容器ID?不管怎样,你也帮了我很多。
  • 这取决于实际的标记。不过,在您的情况下,它可能会起作用,但您需要进行额外的检查。

标签: javascript jquery


【解决方案1】:

如果您不需要每个 div(p 和 h1)的内容具有交互元素(例如表单项),那么您可以添加一个不可点击的额外 div 包装器:)。现在您的所有点击目标都将是第一个子 div。

document.querySelector("#container").addEventListener("click", (e) =&gt; console.log(e.target))
.unclickable {
   pointer-events:none;
}
<div id="container">
          <div>
             <div class="unclickable">
               <h1>Element 1</h1>
               <p>Lorem ipsum...</p>
             </div>
          </div>
          <div>
             <div class="unclickable">
               <h1>Element 2</h1>
               <p>Lorem ipsum...</p>
             </div>
          </div>
</div>

【讨论】:

    【解决方案2】:

    鉴于您在问题下的 cmets,您的目标是找到一种有效的方法来确定用户是否单击了外部 div 或其中一个子元素。

    为此,您将事件的target 属性(引发事件的元素)与currentTarget 属性(始终是事件绑定到的元素)进行比较。逻辑看起来像这样:

    $('#container').on('click', e => {
      if (e.target == e.currentTarget) {
        console.log('clicked on parent');
      } else {
        console.log(`clicked on child element - ${e.target.tagName}`);
      }
    });
    #container {
      border: 1px solid #000;
      padding: 10px;
    }
    
    #container > div {
      display: inline-block;
      border: 1px solid #CCC;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <div id="container">
      <div>
        <h1>Element 1</h1>
        <p>Lorem ipsum...</p>
      </div>
      <div>
        <h1>Element 2</h1>
        <p>...dolor sit amet...</p>
      </div>
    </div>

    请注意,上面示例中的 CSS 只是为了让每个元素的边界更加明显。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-09-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多