首页 > 解决方案 > 当鼠标在子元素之间移动时,如何不被 mouseover/mouseout 事件发送垃圾邮件?

问题描述

最好用一个例子来解释:

var root = document.querySelector("#a");
var msg_stack = document.querySelector("#msg_stack");
var last_msg = document.querySelector("#dummy");

function pad(v) {
  v = "" + v;
  while (v.length < 3) v = "0" + v;
  return v;
}

function hover(v) {
  var msg = document.createElement("div");
  msg.innerText = pad(msg_stack.children.length) + ": " + v;
  
  last_msg = msg_stack.insertBefore(msg, last_msg);
}

root.addEventListener("mouseover", function() { hover(true); });
root.addEventListener("mouseout", function() { hover(false); });
#a {
  position:absolute;
  left:10px;top:10px;width:200px;height:50px;
  background-color:red;
}

#b {
  position:absolute;
  right:0px;top:0px;width:50px;height:200px;
  background-color:red;
}

#b:after {
  content:"";
  position:absolute;
  left:0;top:0;height:50px;
  border-left:solid 1px blue;
}

#msg_stack {
  position:absolute;
  left:230px;top:10px;width:500px;height:200px;
}
<div id="a"><div id="b"></div></div>
<div id="msg_stack"><div id="dummy"></div></div>

请注意,当您将鼠标移到蓝色边框上同时仍停留在红色边框内时,它会被不必要的 mouseout/mouseover 事件发送垃圾邮件。

就我而言,这很昂贵,在我的网页中,我的元素彼此叠加了 5 层,因此垃圾邮件更加严重。每次鼠标悬停/鼠标移出都会触发一堆其他事情,如果这种情况在一毫秒内发生 10 倍,它会让事情变得卡顿。

我不想禁用向上传递 html 层次结构的事件(如在 #a 中触发鼠标事件的 #b 中),这是可取的,因为我在页面上监控的东西也有奇怪的形状。

如果鼠标没有真正离开受监视元素及其子元素的范围,有没有办法不被 mouseout/mouseover 发送垃圾邮件?

或者,有没有办法在处理当前(鼠标悬停)事件时检测到另一个事件(随后的鼠标悬停)正在从管道中下来?

目前我在每次触发事件时设置一个变量,然后一个 1ms 超时循环检查该变量,然后触发需要在 mouseover/mouseut 上发生的其他操作,但我不喜欢它。

标签: javascript

解决方案


您想要mouseenterandmouseleave事件而不是mouseoverand mouseout

mouseover并且mouseout当任何子元素获得或失去鼠标时触发事件。mouseenter并且mouseleave事件仅在处理事件的元素第一次进入或完全离开时触发。

这是有关差异的更多信息

var root = document.querySelector("#a");
var msg_stack = document.querySelector("#msg_stack");
var last_msg = document.querySelector("#dummy");

function pad(v) {
  v = "" + v;
  while (v.length < 3) v = "0" + v;
  return v;
}

function hover(v) {
  var msg = document.createElement("div");
  msg.innerText = pad(msg_stack.children.length) + ": " + v;
  
  last_msg = msg_stack.insertBefore(msg, last_msg);
}

root.addEventListener("mouseenter", function() { hover(true); });
root.addEventListener("mouseleave", function() { hover(false); });
#a {
  position:absolute;
  left:10px;top:10px;width:200px;height:50px;
  background-color:red;
}

#b {
  position:absolute;
  right:0px;top:0px;width:50px;height:200px;
  background-color:red;
}

#b:after {
  content:"";
  position:absolute;
  left:0;top:0;height:50px;
  border-left:solid 1px blue;
}

#msg_stack {
  position:absolute;
  left:230px;top:10px;width:500px;height:200px;
}
<div id="a"><div id="b"></div></div>
<div id="msg_stack"><div id="dummy"></div></div>


推荐阅读