[英]JavaScript - Attaching event handlers to an element also attaches them to its children
我有这个HTML。 我只想将mouseover和mouseleave事件附加到.parent
元素,但是由于某些原因,它们也附加到children元素,所以我的行为很奇怪。
<div class="parent">
<div class="child-1"></div>
<div class="child-2"></div>
</div>
这是我的方法
const parent = document.getElementsByClassName('parent')[0]
parent.addEventListener('mouseover', eventHandler)
parent.addEventListener('mouseleave', eventHandler)
发生了什么事以及如何预防?
您必须将事件添加到子节点并取消事件的传播。
const parent = document.getElementsByClassName('parent')[0] parent.addEventListener('mouseover', eventHandler) parent.addEventListener('mouseleave', eventHandler) for (const child of parent.childNodes) { child.addEventListener('mouseover', function(event) { event.stopPropagation(); }) child.addEventListener('mouseleave', function(event) { event.stopPropagation(); }) } function eventHandler() { console.log('hey'); }
<div class="parent" style="width: 25px; height: 25px; background: red; padding: 50px"> <div class="child-1" style="width: 25px; height: 25px; background: blue"></div> <div class="child-2" style="width: 25px; height: 25px; background: green"></div> </div>
或者您可以做每个人都想要的pointer-event
const parent = document.getElementsByClassName('parent')[0] parent.addEventListener('mouseover', eventHandler) parent.addEventListener('mouseleave', eventHandler) for (const child of parent.childNodes) { child.className += ' no-event' } function eventHandler() { console.log('hey'); }
.no-event { pointer-events: none; }
<div class="parent" style="width: 25px; height: 25px; background: red; padding: 50px"> <div class="child-1" style="width: 25px; height: 25px; background: blue"></div> <div class="child-2" style="width: 25px; height: 25px; background: green"></div> </div>
它必须完成事件捕获和冒泡的工作方式。 我复制了@ACD答案,以查看它的行为是否有所不同。 如果您注意到我们是否将鼠标悬停在孩子上并移到父对象上,则在此示例中未调用该事件。 因此,子元素不再是事件的目标。
该活动分为两个阶段:捕捉和冒泡。 您可以在此处找到更多信息。 该事件是为孩子触发的,它正在冒泡给父事件。 您可以通过event.target
检查事件目标
如果我们删除pointer-events: none;
那么目标是孩子而不是父母。 并在调用子处理程序之后,将通风口传播到父级,然后调用父级回调。
const parent = document.getElementsByClassName('parent')[0] parent.addEventListener('mouseover', eventHandler) parent.addEventListener('mouseleave', eventHandler) function eventHandler(e) { console.log(e.target, 'hey'); }
<div class="parent" style="width: 25px; height: 25px; background: red; padding: 50px"> <div class="child-1" style="pointer-events: none; width: 25px; height: 25px; background: blue"></div> <div class="child-2" style="pointer-events: none; width: 25px; height: 25px; background: green"></div> </div>
尝试使用mouseenter
和mouseleave
而不是mouseover
和mouseleave
。 不要把它们混在一起。 这是mouseover/mouseout
或mouseenter/mouseleave
组合,因为这些组合是对称的。
https://developer.mozilla.org/zh-CN/docs/Web/Events/mouseenter
var logs = document.querySelector('.log'); var area = document.querySelector('.parent'); function eventHandler (e) { if (e.type === 'mouseenter') { area.style.backgroundColor = '#c00'; } else { area.style.backgroundColor = ''; } } area.addEventListener('mouseenter', eventHandler); area.addEventListener('mouseleave', eventHandler);
.parent { background: #eee; } .child { padding: 30px 20px; } .child + .child { border-top: 1px dotted #333; }
<div class="parent"> <div class="child"> foo bar baz </div> <div class="child"> foo bar baz </div> </div>
您可以通过应用CSS来解决此问题
.child-1, .child-2 {
pointer-events: none
}
对孩子来说,这样就不可能与孩子互动。
另外,在事件处理程序中,您可以检查event.target
是父节点还是子节点,将鼠标悬停在子.parent
上将产生子节点,将鼠标悬停在.parent
上将产生父节点。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.