将鼠标移出图层会导致子元素上的事件冒泡:
在基于层的导航中,您可能需要知道鼠标何时离开层以便关闭它。因此,您将 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(层),则立即结束函数,因为鼠标肯定没有离开层。
如果目标是图层,我们仍然不确定鼠标是离开图层还是进入图层内的链接。因此我们要检查事件的relatedTarget/toElement,即。鼠标移动到的元素。
我们读出这个元素,然后我们将在 DOM 树中向上移动,直到遇到事件的目标(即 DIV)或 body 元素。
如果我们遇到目标鼠标移向层的子元素,那么鼠标实际上并没有离开层。我们停止该功能。
当函数通过所有这些检查时,我们可以确定鼠标实际上已经离开了图层,我们可以采取适当的行动(通常使图层不可见)。
鼠标进入和鼠标离开:
微软有另一个解决方案。它创建了两个新事件 mouseenter 和 mouseleave。它们几乎与 mouseover 和 mouseout 相同,只是它们不对事件冒泡做出反应。因此,他们将注册到的整个 HTML 元素视为一个实体块,并且不会对块内发生的鼠标悬停和 -out 做出反应。
所以使用这些事件也解决了我们的问题:它们只对它们注册到的元素上的鼠标悬停/离开作出反应。
目前,这些事件仅受 Windows 及更高版本的 Explorer 5.5 支持。也许其他浏览器供应商会复制这些事件。
所以最好使用 mouseleave 而不是 mouseout,因为它会导致事件冒泡。