我有一个包含多个子元素的父元素,其中一些有自己的事件侦听器,而另一些则没有。父元素具有单击处理程序,仅当我单击父元素本身而不是任何子元素时,我才想运行该处理程序。
document.getElementById('parent').addEventListener('click', ()=> console.log('parent clicked'))
document.getElementById('child2').addEventListener('click', ()=> console.log('child2 clicked'))
#parent {
height: 300px;
width: 300px;
background-color: Lightgreen;
wrap: true;
display: flex;
flex-direction:column;
gap: 20px;
padding: 50px 50px;
}
#parent * {
height: 100px;
width: 100px;
background-color: white;
text-align: center;
display: grid;
place-items: center;
}
<div id="parent"> parent -Only log 'parent' when green background is clicked and nothing else-
<div id="child1">child1 <br> -Nothing should happen when clicked-</div>
<div id="child2">child2 <br> -Should only log -child 2 if clicked-</div>
</div>
我尝试了stopPropagation()
,它可以阻止事件冒泡,但我需要将其添加到所有子事件处理程序中,并且我仍然无法阻止父级在单击没有事件侦听器的对象时触发。
有没有办法仅在单击元素本身时限制父处理程序?
event.currentTarget
可能有助于验证事件是否来自设置事件的特定元素,而不是来自子元素。从 MDN 的文档快速定义它:
Event
接口的currentTarget
只读属性在事件遍历 DOM 时标识事件的当前目标。它始终引用事件处理程序附加到的元素,而不是Event.target
,后者标识事件发生的元素,并且可能是其后代。
在@CertainPerformance的解决方案上这样做的好处(这很棒)是你不必知道那个元素。
document.getElementById('parent').addEventListener('click', (e)=> {
if(e.currentTarget===e.target){
console.log('parent clicked');
}
});
document.getElementById('child2').addEventListener('click', (e)=> {
if(e.currentTarget===e.target){
console.log('child2 clicked');
}
});
#parent {
height: 300px;
width: 300px;
background-color: Lightgreen;
wrap: true;
display: flex;
flex-direction:column;
gap: 20px;
padding: 50px 50px;
}
#parent * {
height: 100px;
width: 100px;
background-color: white;
text-align: center;
display: grid;
place-items: center;
}
<div id="parent"> parent -Only log 'parent' when green background is clicked and nothing else-
<div id="child1">child1 <br> -Nothing should happen when clicked-</div>
<div id="child2">child2 <br> -Should only log -child 2 if clicked-</div>
</div>
这只是对这个答案的一个小补充,并不是一个答案。e.currentTarget === e.target
点击子项的事件可能会触发parent clicked
如果pointer-events: none
用于子项。
但是如果使用pointer-events: none
那么无论如何你都不能做任何事情,因为明确地说这个元素应该被忽略以进行事件处理。
document.getElementById('parent').addEventListener('click', (e) => {
if (e.currentTarget === e.target) {
console.log('parent clicked');
}
});
#parent {
height: 300px;
width: 300px;
background-color: Lightgreen;
wrap: true;
display: flex;
flex-direction: column;
gap: 20px;
padding: 50px 50px;
}
#parent * {
height: 100px;
width: 100px;
background-color: white;
text-align: center;
display: grid;
place-items: center;
}
[data-no-pointer-event] {
pointer-events: none;
}
<div id="parent"> parent -Only log 'parent' when green background is clicked and nothing else-
<div id="child1">child1 <br> - Nothing should happen when clicked -</div>
<div id="child2" data-no-pointer-event>child 2 - will log parent clicked - </div>
</div>
检查.target
是否是父级 - 如果是,则意味着点击直接在父级上,而不是从孩子冒泡的事件。
const parent = document.getElementById('parent');
parent.addEventListener('click', (e) => {
if (e.target === parent) {
console.log('parent clicked');
}
});
document.getElementById('child2').addEventListener('click', () => console.log('child2 clicked'))
#parent {
height: 300px;
width: 300px;
background-color: Lightgreen;
wrap: true;
display: flex;
flex-direction: column;
gap: 20px;
padding: 50px 50px;
}
#parent * {
height: 100px;
width: 100px;
background-color: white;
text-align: center;
display: grid;
place-items: center;
}
<div id="parent"> parent -Only log 'parent' when green background is clicked and nothing else-
<div id="child1">child1 <br> -Nothing should happen when clicked-</div>
<div id="child2">child2 <br> -Should only log -child 2 if clicked-</div>
</div>