Javascript '的意外行为;onmouseout';在“a”中;“悬停菜单”;

Javascript '的意外行为;onmouseout';在“a”中;“悬停菜单”;,javascript,menu,hover,onmouseout,Javascript,Menu,Hover,Onmouseout,我正在尝试创建一个“悬停菜单”-将鼠标悬停在标题上,然后在标题下方出现一个菜单框-我希望当您将鼠标移到标题外时,菜单框消失 看: 将鼠标悬停在“STUFF”上-菜单框显示在下方。现在开始慢慢移动鼠标光标-向下-一旦你通过第一个项目-它消失! 这不是所需的操作 显然,我的onmouseout定义在#menuStuffdiv上,您可以清楚地看到Firebug的尺寸-它占据了整个列表的宽度和高度- 所以为什么从第一个列表项向下移动后会触发?光标仍在div的边界内-这是怎么回事?鼠标移出层会导致子元素

我正在尝试创建一个“悬停菜单”-将鼠标悬停在标题上,然后在标题下方出现一个菜单框-我希望当您将鼠标移到标题外时,菜单框消失

看:

将鼠标悬停在“STUFF”上-菜单框显示在下方。现在开始慢慢移动鼠标光标-向下-一旦你通过第一个项目-它消失! 这不是所需的操作
显然,我的
onmouseout
定义在
#menuStuff
div上,您可以清楚地看到Firebug的尺寸-它占据了整个列表的宽度和高度-
所以为什么从第一个列表项向下移动后会触发?光标仍在div的边界内-这是怎么回事?

鼠标移出层会导致子元素上的事件冒泡:

在基于图层的导航中,您可能需要知道鼠标何时离开某个图层,以便将其关闭。因此,将onmouseout事件处理程序注册到该层。但是,当鼠标离开层内的任何元素时,事件冒泡也会导致触发此事件处理程序

--------------
| Layer      |.onmouseout = doSomething;
| --------   |
| | Link | ----> We want to know about this mouseout
| |      |   |
| --------   |
| --------   |
| | Link |   |
| |    ----> | but not about this one
| --------   |
--------------
---->: mouse movement
另一个阻止显示的因素是,当您将鼠标移动到图层中,然后移动到链接上时,浏览器会在图层上注册一个mouseout事件!这对我来说没有多大意义(鼠标仍在层中),但所有浏览器都同意这一点

那么,当鼠标实际离开图层时,我们如何拒绝任何没有发生的鼠标移出呢

function doSomething(e) {
if (!e) var e = window.event;
var tg = (window.event) ? e.srcElement : e.target;
if (tg.nodeName != 'DIV') return;
var reltg = (e.relatedTarget) ? e.relatedTarget : e.toElement;
while (reltg != tg && reltg.nodeName != 'BODY')
    reltg= reltg.parentNode
if (reltg== tg) return;
// Mouseout took place when mouse actually left layer
// Handle event
}
首先获取事件目标,即鼠标移出的元素。如果目标不是DIV(层),请立即结束该函数,因为鼠标肯定没有离开该层

如果目标是层,我们仍然不确定鼠标是否离开了层或在层内输入了链接。因此,我们将检查事件的相关Target/toElement,即鼠标移动到的元素

我们读出这个元素,然后在DOM树中向上移动,直到遇到事件的目标(即DIV)或body元素

如果我们遇到目标,鼠标将移向层的子元素,因此鼠标实际上没有离开层。我们停止这个功能

当函数通过所有这些检查后,我们可以确定鼠标确实离开了图层,我们可以采取适当的措施(通常使图层不可见)

Mouseenter和mouseleave:

微软有另一个解决方案。它创建了两个新事件mouseenter和mouseleave。它们与mouseover和mouseout几乎相同,只是它们不会对事件冒泡做出反应。因此,他们将注册到的整个HTML元素视为一个实体块,不会对块内发生的鼠标移动和–out做出反应

因此,使用这些事件也解决了我们的问题:它们只对它们注册到的元素上的鼠标溢出/移出做出反应

目前,只有Windows及更高版本的Explorer 5.5支持这些事件。也许其他浏览器供应商会复制这些事件


因此,最好使用mouseleave而不是mouseout,因为它会导致事件冒泡。

如果使用jQuery,可以在div上使用mouseleave事件:

使用onmouseleave代替onmouseout:



jshiddle->

问题标题很奇怪。好吧,我会把它改成一个无聊的问题。这不是无聊的有趣问题,而是与你的问题相关的问题,这样你就可以从别人那里得到更好的帮助,因为问题本身是好的。我知道为什么要让它变得消极。这两个版本的标题有着完全相同的含义,第一个版本需要承认一个流行的互联网模因。没关系,我更改了它…抱歉,这不是期望的结果-一旦你尝试在菜单框内移动,它就会消失。我对你的问题进行了彻底的研究并找到了解决方案。我已更新了我的答案。请查看。
$('#menuStuff').mouseleave(function(){
    $('#menuStuff').hide();
});
<div id="menuStuff" class="hover-menu" onmouseleave="$('#menuStuff').hide();" >