简体   繁体   English

JavaScript-将事件处理程序附加到元素还将其附加到其子元素

[英]JavaScript - Attaching event handlers to an element also attaches them to its children

I have this HTML. 我有这个HTML。 I want to attach mouseover and mouseleave events ONLY to the .parent element, but for some reason they also get attached to the children elements and I get weird behaviour. 我只想将mouseover和mouseleave事件附加到.parent元素,但是由于某些原因,它们也附加到children元素,所以我的行为很奇怪。

<div class="parent">
  <div class="child-1"></div>
  <div class="child-2"></div>
</div>

Here's how I do it 这是我的方法

const parent = document.getElementsByClassName('parent')[0]
parent.addEventListener('mouseover', eventHandler)
parent.addEventListener('mouseleave', eventHandler)

Whats going on and how to prevent it? 发生了什么事以及如何预防?

You have to add event to child nodes and cancel the propagation of the event. 您必须将事件添加到子节点并取消事件的传播。

 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> 

Or you could do what everyone wants pointer-event 或者您可以做每个人都想要的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> 

It has to do how event catching and bubbling works. 它必须完成事件捕获和冒泡的工作方式。 I copied the @ACD answer to see that it does behave differently. 我复制了@ACD答案,以查看它的行为是否有所不同。 If you notice if we hover on child and move out to the parent the event is not called in this example. 如果您注意到我们是否将鼠标悬停在孩子上并移到父对象上,则在此示例中未调用该事件。 So child elements are no more the target of the event. 因此,子元素不再是事件的目标。

There are two phases of the event, Catching and Bubbling. 该活动分为两个阶段:捕捉和冒泡。 You can find more information here . 您可以在此处找到更多信息。 What is happening that event is triggered for the child and it is bubbling to the parent. 该事件是为孩子触发的,它正在冒泡给父事件。 You can check the event target via event.target 您可以通过event.target检查事件目标

If we remove pointer-events: none; 如果我们删除pointer-events: none; then the target is the child not the parent . 那么目标是孩子而不是父母。 and after the child handler is called the vent is propagated to the parent and then the parents callback is called. 并在调用子处理程序之后,将通风口传播到父级,然后调用父级回调。

 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> 

Try mouseenter and mouseleave instead of mouseover and mouseleave . 尝试使用mouseentermouseleave而不是mouseovermouseleave Don't mix them up. 不要把它们混在一起。 It's either the combination of mouseover/mouseout or mouseenter/mouseleave , because these combos are symmetrical. 这是mouseover/mouseoutmouseenter/mouseleave组合,因为这些组合是对称的。

https://developer.mozilla.org/en-US/docs/Web/Events/mouseenter 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> 

You could fix this with css, by applying 您可以通过应用CSS来解决此问题

.child-1, .child-2 {
  pointer-events: none
}

to the children, that way no interaction with the children is possible. 对孩子来说,这样就不可能与孩子互动。

Alternatively, in the eventhandler you could check if the event.target is the parent or a childnode, hovering over a childnode will yield the childnode, hovering over .parent will yield the parent. 另外,在事件处理程序中,您可以检查event.target是父节点还是子节点,将鼠标悬停在子.parent上将产生子节点,将鼠标悬停在.parent上将产生父节点。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 附加事件处理程序优化javascript - Attaching Event Handlers Optimization javascript 附加和重新附加事件处理程序 - Attaching and reattaching Event Handlers 使用javascript在循环中注入元素并附加Click事件处理程序 - Injecting elements and attaching Click event handlers in a loop with javascript 使用纯JavaScript将事件处理程序附加到使用类动态创建的元素上 - Attaching Event handlers to dynamically created elements with a class using plain JavaScript 在CSS和本机Javascript中选择没有任何子元素的父元素 - Selecting parent element without any of its children in CSS and also in native Javascript 事件委托:在Element而不是其子元素上捕获事件 - Event Delegation : catch event on Element not its children Javascript 检测 HTML 元素上可用的事件处理程序 - Javascript detect event handlers available on HTML element 有没有办法用 Javascript 找到元素的事件处理程序? - Is there a way to find the event handlers of an element with Javascript? JavaScript中的事件处理程序,用于逐步增强的`select`元素 - Event handlers in JavaScript for a progressively enhanced `select` element 在循环中创建动态 div 元素并附加事件处理程序时,仅为最后一个元素触发事件 - When creating dynamic div elements in a loop and attaching event handlers, event is fired for last element only
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM