Mik*_* Li 21 javascript css jquery html5
子和父都可以点击(子可以是jQuery点击事件的链接或div).当我点击child时,我如何只触发父点击事件而不触发子事件?
Mak*_*yen 77
活动分为三个阶段:
<window>
并向下移动到事件的目标.事件也有一个"默认动作",它发生在冒泡阶段之后.默认动作是通常发生为是事件的目标的种类元素的指定类型的事件(浏览器定义的动作例如在浏览器导航到href
的<a>
在一个click
,而click
在另一种类型的元件的会有不同的默认操作).
在DOM级别3事件草案有一个图,以图形方式显示事件通过DOM如何传播:
图像版权所有©2016 World Wide Web Consortium,(麻省理工学院,ERCIM,Keio,北京).http://www.w3.org/Consortium/Legal/2015/doc-license(根据许可证允许使用)
有关捕获和冒泡的更多信息,请参阅:" 什么是事件冒泡和捕获? "; 在DOM Level 3的草稿活动 ; 或者W3C DOM4:事件
对于您想要的内容,要在父级之前获取事件并阻止该事件,您必须在捕获阶段接收事件.一旦在捕获阶段收到它,就必须阻止事件传播到DOM树中较低元素的任何事件处理程序,或者已注册在冒泡阶段监听的事件(即元素/阶段上的所有侦听器在听众之后参加活动).你通过电话来做到这一点event.stopPropagation()
.
添加侦听器时addEventListener(type, listener[, useCapture])
,可以使用useCapture
参数true
.
引用MDN:
[
useCapture
是]一个布尔值,指示在将此类型的事件分派到DOM树中位于其下的任何EventTarget之前,将将其分派给已注册的侦听器.向上冒泡到树中的事件不会触发指定使用捕获的侦听器.事件冒泡和捕获是传播发生在被嵌套在另一个元件之内,当两个元件已经注册了该事件的手柄元件的事件的方法有两种.事件传播模式确定元素接收事件的顺序.有关详细说明,请参阅DOM Level 3事件和JavaScript事件顺序.如果未指定,则useCapture
默认为false.
event.preventDefault()
用于防止默认动作(例如防止浏览器导航到href
的<a>
在一个click
).[这在下面的示例中使用,但没有实际效果,因为文本没有默认操作.它在这里使用是因为大多数情况下,当您添加单击事件处理程序时,您希望阻止默认操作.因此,养成这样做的习惯是个好主意,当你知道自己不想这样做时就不这样做.event.stopPropagation()
用于防止任何事件阶段中的元素上的任何处理程序接收事件.它不会阻止调用当前元素和阶段上的任何其他处理程序.它不会阻止发生默认操作.event.stopImmediatePropagation()
:处理相同元素和阶段的处理程序按添加顺序调用.除了具有相同的效果之外event.stopPropagation()
,还event.stopImmediatePropagation()
防止同一元素和事件阶段的任何其他处理程序接收事件.它不会阻止发生默认操作.鉴于这个问题的要求是防止事件传播给孩子,我们不需要使用它,但可以这样做而不是使用event.stopPropagation()
.但请注意,同一元素上的侦听器按其添加顺序调用.因此,event.stopImmediatePropagation()
不会阻止那些侦听器在与听众相同的元素和阶段接收事件.在以下示例中,事件侦听器放置在父<div>
元素和子元素上.只有放在父级上的侦听器才会收到该事件,因为它在子级之前的捕获阶段接收事件并执行event.stopPropagation()
.
var parent=document.getElementById('parent');
var child=document.getElementById('child');
var preventChild=document.getElementById('preventChild');
parent.addEventListener('click',function(event){
if(preventChild.checked) {
event.stopPropagation();
}
event.preventDefault();
var targetText;
if(event.target === parent) {
targetText='parent';
}
if(event.target === child) {
targetText='child';
}
console.log('Click Detected in parent on ' + targetText);
},true);
child.addEventListener('click',function(event){
console.log('Click Detected in child (bubbling phase)');
});
child.addEventListener('click',function(event){
console.log('Click Detected in child (capture phase)');
},true);
Run Code Online (Sandbox Code Playgroud)
<input id="preventChild" type="checkbox" checked>Prevent child from getting event</input>
<div id="parent">Parent Text<br/>
<div id="child" style="margin-left:10px;">Child Text<br/>
</div>
</div>
Run Code Online (Sandbox Code Playgroud)
jQuery不支持在事件上使用捕获.有关为什么看到的更多信息:" 为什么jQuery事件模型不支持事件Capture并且只支持事件冒泡 "
Abr*_*kes 17
如果您知道没有任何子元素是交互式的,则在某些情况下可能有用的另一个选项是pointer-events: none
在您的css(链接)中设置.我通常将它应用于我想要捕获交互的元素的所有子元素.像这样:
#parentDiv * {
pointer-events: none
}
Run Code Online (Sandbox Code Playgroud)
请注意*
,声明该规则适用于该规则的所有子项parentDiv
.
children
接收父级的点击事件:parent.addEventListener('click',function(e){
e.stopPropagation();
console.log('event on parent!')
},true);
Run Code Online (Sandbox Code Playgroud)
(注意第二个参数是true
)
parent
接收自身或其子级的点击事件:parent.addEventListener('click',function(e){
e.stopPropagation();
console.log('event on parent or childs!', e.target.closest('.parent_selector'))
});
Run Code Online (Sandbox Code Playgroud)
e.stopPropagation
意味着停止层次结构中的下一个来接收事件。useCapture
) 是一个标志,表示颠倒接收事件的顺序。(使用capture
阶段而不是bubble
阶段。)。这意味着如果将其设置为 true,则父级将收到单击事件,然后是子级。(通常孩子会先收到事件。)(有关详细说明,请参阅@Makyen 的答案。)