如何禁用由子元素触发的mouseout事件?


107

让我详细描述问题:

我想在将鼠标悬停在元素上时显示绝对定位的div。使用jQuery确实很简单,并且效果很好。但是,当鼠标悬停在子元素之一上时,它将触发包含div的mouseout事件。悬停子元素时,如何防止javascript触发包含元素的mouseout事件。

用jQuery做到最好和最短的方法是什么?

这是一个简化的示例来说明我的意思:

HTML:

<a>Hover Me</a>
<div>
  <input>Test</input>
  <select>
    <option>Option 1</option>
    <option>Option 2</option>
  </select>
</div>

Javascript / jQuery:

$('a').hover( function() { $(this).next().show() }
              function() { $(this).next().hide() } );

Answers:


209

这个问题有点老了,但是前几天我碰到了这个问题。

使用最新版本的jQuery进行此操作的最简单方法是使用mouseenterand mouseleave事件而不是mouseoverand mouseout

您可以使用以下方法快速测试行为:

$(".myClass").on( {
   'mouseenter':function() { console.log("enter"); },
   'mouseleave':function() { console.log("leave"); }
});

4
帮助了我的非jquery javascript相关问题。我在事件监听器中使用的是mouseenter / mouseout而不是mouseleave!
Jo E.

1
为了搜索起见,这些鼠标事件行为ROLL_OVERROLL_OUTAS3 中的等效。
杰夫·沃德

2
救了我一些头疼。悬停在子元素上触发父mouseout事件的方式很奇怪,而实际上它仍在父元素内。
javiniar.leonard

18

为简单起见,我将稍微重新组织html以便将新显示的内容放入mouseover事件绑定到的元素中:

<div id="hoverable">
  <a>Hover Me</a>
  <div style="display:none;">
    <input>Test</input>
    <select>
      <option>Option 1</option>
      <option>Option 2</option>
    </select>
  </div>
</div>

然后,您可以执行以下操作:

$('#hoverable').hover( function() { $(this).find("div").show(); },
                       function() { $(this).find("div").hide(); } );

注意:我不建议使用内联CSS,但是这样做是为了使示例更易于理解。


这确实是一个非常简单和干净的解决方案。谢谢你的提醒。但是在我的具体情况下(这与问题不完全相同),这是一个选择。不过谢谢!
Sander Versluys

在尝试了SO其他人描述的不同方法之后,我回到了您的方法并使之适用于我的情况。好极了!:-)
Sander Versluys

11

是的,伙计们,请使用.mouseleave代替.mouseout

$('div.sort-selector').mouseleave(function() {
    $(this).hide();
});

甚至与live以下内容结合使用:

$('div.sort-selector').live('mouseleave', function() {
    $(this).hide();
});

8

您正在寻找与javascript的prevent事件冒泡等效的jQuery。

看一下这个:

http://docs.jquery.com/Events/jQuery.Event#event.stopPropagation.28.29

基本上,您需要在子DOM节点中捕获事件,然后停止它们在DOM树上的传播。尽管实际上不建议这样做(因为它可能会严重干扰页面上的现有事件),但是另一种方法是将事件捕获设置为页面上的特定元素,它将接收所有事件。这对于DnD行为等很有用,但绝对不适用于您的情况。


这样就可以正常工作了,不知道为什么您无法使它工作。 28.29
zappan

3

我只是在检查鼠标坐标是否在mouseout-event中的元素之外。

它可以工作,但是对于这么简单的事情,它有很多代码:(

function mouseOut(e)
{
    var pos = GetMousePositionInElement(e, element);
    if (pos.x < 0 || pos.x >= element.size.X || pos.y < 0 || pos.y >= element.size.Y)
    {
        RealMouseOut();
    }
    else
    {
         //Hit a child-element
    }
}

出于可读性考虑,代码已缩减,无法立即使用。


1

我同意赖安。

您的问题是“下一个” div不是A的“子”。HTML或jQuery无法知道您的“ a”元素与DOM中的子div有关。包装它们并将鼠标悬停在包装上意味着它们是关联的。

请注意,他的代码与最佳做法不符。不要在元素上设置隐藏样式。如果用户具有CSS而不是javascript,则该元素将隐藏并且无法显示。更好的做法是将该声明放入document.ready事件中。


我完全同意将hide放入document.ready事件中。内联CSS只是以最简单的方式传达完整的工作示例。我将编辑我的回复以使其清楚。
Ryan McGeary

1

我通过添加pointer-events: none;子元素css 解决了这个问题


当修复一些旧代码,用mouseover和mouseleave事件构建自己的弹出窗口时,这确实起到了很大的帮助
CM

0

我通常看到的处理方式是,从HoverMe元素移出鼠标之间会有大约1/2秒的延迟。将鼠标移到悬停的元素上时,您需要设置一些变量,以表示您将鼠标悬停在元素上,然后,如果设置了此变量,则基本上可以阻止隐藏的部分隐藏。然后,您必须从悬停的元素中添加类似的隐藏函数OnMouseOut,以使其在删除鼠标时消失。抱歉,我不能给您任何代码,或更具体的内容,但是我希望这可以为您指明正确的方向。


是的,idd我刚刚实现了这样的解决方案。这是一个非常普遍的问题。我真的很好奇还有什么其他解决方案...感谢您的回答!
Sander Versluys

0

这是一个古老的问题,但是永远不会过时。正确的答案应该是bytebrite给出的答案

我只想指出mouseover / mouseout和mouseenter / mouseleave之间的区别。您可以在此处阅读一个很棒且有用的解释(请转到页面的最底部以获取有效的演示)。当您使用时mouseout,事件将在鼠标输入另一个元素(即使它是子元素)时停止。另一方面,当您使用mouseleave时,鼠标悬停在子元素上时不会触发该事件,这是OP希望实现的行为。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.