子项和父项都是可点击的(子项可以是带有 jQuery 单击事件的链接或 div)。当我点击子项时,如何只触发父级点击事件而不触发子级事件?
原文由 Mike Li 发布,翻译遵循 CC BY-SA 4.0 许可协议
子项和父项都是可点击的(子项可以是带有 jQuery 单击事件的链接或 div)。当我点击子项时,如何只触发父级点击事件而不触发子级事件?
原文由 Mike Li 发布,翻译遵循 CC BY-SA 4.0 许可协议
13 回答13k 阅读
7 回答2.1k 阅读
3 回答1.3k 阅读✓ 已解决
3 回答872 阅读✓ 已解决
6 回答1.2k 阅读✓ 已解决
2 回答1.4k 阅读✓ 已解决
4 回答1.3k 阅读✓ 已解决
DOM 事件阶段
事件分为三个阶段:
<window>
开始被调用,并通过后代向下移动到事件的目标。事件也有一个“默认动作”,它发生在冒泡阶段之后。默认操作是浏览器定义的操作,通常针对作为事件目标的元素类型的指定类型的事件发生(例如,浏览器导航到
href
的<a>
在click
上,而在另一种类型的元素上click
将具有不同的默认操作)。DOM Level 3 Events 草案 有一个图表,以图形方式显示事件如何通过 DOM 传播:
图片版权 © 2016 万维网联盟,( 麻省理工学院、 ERCIM 、 庆应义塾、 北航)。 http://www.w3.org/Consortium/Legal/2015/doc-license ( 根据许可证 允许使用)
有关捕获和冒泡的更多信息,请参阅:“ 什么是事件冒泡和捕获? ”; DOM Level 3 事件草案;或 W3C DOM4:事件
防止事件传给孩子
对于您想要的,要在父级事件之前获取事件并防止事件发生在子级上,您必须在捕获阶段接收事件。一旦您在捕获阶段收到它,您必须阻止事件传播到 DOM 树中较低元素上的任何事件处理程序,或者已注册为在冒泡阶段侦听的事件处理程序(即元素/阶段上的所有侦听器将在你的听众之后被事件访问)。您可以通过调用
event.stopPropagation()
来执行此操作。在捕获阶段接收事件
使用
addEventListener(type, listener[, useCapture])
添加侦听器时,您可以将useCapture
参数设为true
。引用 MDN:
防止其他处理程序获取事件
event.preventDefault()
is used to prevent the default action (eg prevent the browser from navigating to thehref
of an<a>
upon aclick
). [这在下面的示例中使用,但没有实际效果,因为文本没有默认操作。此处使用它是因为大多数情况下,当您添加单击事件处理程序时,您希望阻止默认操作。因此,养成这样做的习惯是个好主意,当你知道自己不想这样做时就不要这样做。]event.stopPropagation()
用于防止在任何事件阶段之后的元素上的任何处理程序接收事件。它不会阻止调用 当前元素和阶段上的 任何其他处理程序。它不会阻止默认操作的发生。event.stopImmediatePropagation()
: 相同元素和阶段的处理程序按添加顺序调用。除了具有与event.stopPropagation()
相同的效果外,event.stopImmediatePropagation()
还可以防止 同一元素和事件阶段上的 任何其他处理程序接收事件。它不会阻止默认操作的发生。鉴于此问题的要求是防止事件传播给孩子,我们不需要使用它,但可以这样做而不是使用event.stopPropagation()
。但是请注意,同一元素上的侦听器是按添加顺序调用的。因此,event.stopImmediatePropagation()
不会阻止事件被那些在与您的侦听器相同的元素和阶段上的侦听器接收,这些侦听器是在您的侦听器之前添加的。例子
在下面的示例中,事件侦听器被放置在父元素和子元素
<div>
元素上。只有放置在父级上的侦听器才能接收事件,因为它在子级之前的捕获阶段接收到事件并执行event.stopPropagation()
。查询
jQuery 不支持对事件使用捕获。有关原因的更多信息,请参阅:“ 为什么 jQuery 事件模型不支持事件捕获而只支持事件冒泡”