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

时间:2018-11-26 09:50:23

标签: javascript html dom-events

我有这个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)

发生了什么事以及如何预防?

4 个答案:

答案 0 :(得分:1)

您必须将事件添加到子节点并取消事件的传播。

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>

答案 1 :(得分:0)

它必须完成事件捕获和冒泡的工作方式。我复制了@ACD答案,以查看它的行为是否有所不同。如果您注意到我们是否将鼠标悬停在孩子上并移到父对象上,则在此示例中未调用该事件。因此,子元素不再是事件的目标。

该活动分为捕捉和冒泡两个阶段。您可以找到更多信息here。该事件是为孩子触发的,它正在冒泡给父事件。您可以通过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>

答案 2 :(得分:-1)

尝试使用mouseentermouseleave而不是mouseovermouseleave。不要把它们混在一起。这是mouseover/mouseoutmouseenter/mouseleave的组合,因为这些组合是对称的。

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

答案 3 :(得分:-1)

您可以通过应用

使用CSS解决此问题
.child-1, .child-2 {
  pointer-events: none
}

对于孩子们,那样就不可能与孩子们互动。

或者,您可以在事件处理程序中检查event.target是父节点还是子节点,将鼠标悬停在子节点上将产生子节点,将鼠标悬停在.parent上将产生父节点。