簡體   English   中英

JavaScript-將事件處理程序附加到元素還將其附加到其子元素

[英]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> 

嘗試使用mouseentermouseleave而不是mouseovermouseleave 不要把它們混在一起。 這是mouseover/mouseoutmouseenter/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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM