click 事件总是在父元素上触发,尽管在子元素上调用了 stopPropation()

click event always fires on parent element, despite stopPropation() having been called on child element

我有一个看似微不足道的问题,但找不到原因。有一个最小的 html 结构:

<div id="bg">
  <div id="panel"></div>
  <div id="helper"></div>
</div>

Element #helper 有 display:none,并且在 #panel 上的 mousedown 事件上我在 #helper 上设置了 dipslay:block。

问题可以这样简要描述:当我在元素#panel 中单击时,click 事件总是在元素#bg 上触发,尽管所有努力都在#panel 和#helper 上的事件处理程序上停止事件传播。我做了一个代码笔来说明问题:

https://codepen.io/tony124/pen/LYpQzwx?editors=1111

当我在#panel 之外单击时,我进入了控制台:

"onMouseDownBg" "bg" "bg"
"onMouseUpBg" "bg" "bg"
"onClickBg" "bg" "bg"

这是意料之中的。然而,当我点击#panel 时,我得到

"onMouseDownPanel (stop)" "panel" "panel"
"onMouseUpHelper (stop)" "helper" "helper"
"onClickBg" "bg" "bg"

我不明白为什么。甚至没有来自 onMouseDownBg 和 noMouseUpBg 的日志记录。点击事件是如何触发的?

因为您的 onMouseDownPanel 函数使 <div id="helper"> 成为显示块,并且当您释放鼠标按钮时,因为助手是可见的并且由于定位它正在触发 onMouseUpHelper 最后因为它们都是 bg 的子级所以调用 onClickBg

这是关于调用事件的顺序以及处理程序中发生的操作。

  1. onMouseDown 事件:
    • #panel 消耗并取消了事件。
    • #helper 激活
  2. onMouseUp 事件:
    • #helper 消耗并取消了事件。
    • #helper 变得不活跃
  3. onClick 事件:
    • 来自MDN

      An element receives a click event when a pointing device button (such as a mouse's primary mouse button) is both pressed and released while the pointer is located inside the element. If the button is pressed on one element and the pointer is moved outside the element before the button is released, the event is fired on the most specific ancestor element that contained both elements. (emphasis mine)

在这种情况下,最具体的祖先元素是#bg,因此它处理点击事件。


要获得您可能正在寻找的效果,只需将 #helper 元素的激活移动到 onMouseUpPanel 处理程序