鼠标悬停和移出会触发多次

25
我有两个 JS 的事件,分别是 mouseover 和 mouseout。它们用于检查我是否悬停在页面上的面板上。但问题是,当我悬停在面板上时,它会触发(mouseover)好的,但是当我悬停在面板内的另一个元素上时,它会触发mouseout事件,然后再次触发mouseover事件,当我移动到面板的另一部分时。
我只想让 mouseover 和 mouseout 事件触发一次!一次是进入面板,另一次是离开它。有没有办法将 onMouseOver 调用传播到 div.panel 的所有子元素上?这似乎可以解决它。
这是我的事件:

$(document).off("mouseover").on("mouseover", "div.panel", function() {
   var panelSpaceId = $(this).attr("data-spaceId");
   var marker = _.find(scope.markers, function(item) {
     return item.spaceId == panelSpaceId
   })
   google.maps.event.trigger(marker, "mouseover");
   console.log("over" + marker.spaceId);
 });

 $(document).off("mouseout").on("mouseout", "div.panel", function() {
   var panelSpaceId = $(this).attr("data-spaceId");
   var marker = _.find(scope.markers, function(item) {
     return item.spaceId == panelSpaceId
   })
   google.maps.event.trigger(marker, "mouseout");
   console.log("out" + marker.spaceId);
 });
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

1个回答

64
您可以通过使用mouseenter而不是mouseover,以及mouseleave而不是mouseout来避免此问题。原因很简单:mouseenter仅在光标“进入”元素时触发,这包括其子元素 - 因此悬停在元素的子元素上不会重新触发mouseenter事件。
类似的逻辑也适用于mouseleavemouseout之间的区别。您可以看到这种效果发生在由@gilly3创建的一个fiddle中,他在他的答案中回答了一个类似的问题。我没有将您的问题标记为重复,因为您的答案主要是排除mouseover/leave事件而不是询问mouseover/entermouseout/leave之间的区别。
想象一下这有助于理解:
  • 进入指光标进入元素的范围。即使您在子节点中,仍然在范围内,因此不会多次触发。
  • 悬停可以被视为在画布上看到您的元素。如果您将光标放在屏幕上可见的元素上,则会触发鼠标悬停事件。当您的光标移动到子元素上方时,光标不再悬停在父元素上,因此来回移动时事件会一遍又一遍地触发。

这是修改后的代码,我只是用正确的事件替换了有问题的事件:

$(document).off("mouseenter").on("mouseenter", "div.panel", function() {
  var panelSpaceId = $(this).attr("data-spaceId");
  var marker = _.find(scope.markers, function(item) {
    return item.spaceId == panelSpaceId
  })
  google.maps.event.trigger(marker, "mouseenter");
  console.log("over" + marker.spaceId);
});

$(document).off("mouseleave").on("mouseleave", "div.panel", function() {
  var panelSpaceId = $(this).attr("data-spaceId");
  var marker = _.find(scope.markers, function(item) {
    return item.spaceId == panelSpaceId
  })
  google.maps.event.trigger(marker, "mouseleave");
  console.log("out" + marker.spaceId);
});

有没有办法重置事件中的触发器?因为在使用ajax更新页面并重新加载这两个事件后,它们似乎无法正常工作。 - user1186050
@user1186050 这可能属于另一个问题。不过,我可以看到你正在将事件绑定到文档元素上,这应该不是问题。但仅凭这些信息,我无法进行故障排除,你需要提供一个最小可复现示例以便分析。 - Terry
最小化、具体化和可验证的示例(MCVE)。 - Terry
Terry,我在这里发布了问题:http://stackoverflow.com/questions/41645224/trigger-event-not-firing-after-ajax-call - user1186050
4
我正在使用mouseenter和mouseleave,但datatable行中仍会触发多次... - Rahul Sonwanshi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接