多个mouseout事件被触发

5

我了解JavaScript中的不同事件模型(WC3模型与Microsoft模型),以及冒泡和捕获之间的差异。然而,在阅读有关此问题的各种文章几个小时后,我仍然不确定如何正确编写以下看似简单的行为:

如果我有一个外部div和一个内部div元素,则当鼠标离开外部div时,希望触发单个鼠标移出事件。 当鼠标从内部div到外部div跨越时,不应发生任何事情,并且当鼠标从外部div到内部div跨越时,也不应发生任何事情。 只有当鼠标从外部div移动到周围页面时,事件才应该触发。

<div id="outer" style = "width:20em; height:20em; border:1px solid #F00" align = "center" onmouseout="alert('mouseout event!')" >
<div id="inner" style = "width:18em; height:18em; border:1px solid #000"></div>
</div>

现在,如果我将mouseout事件放在外部div上,当鼠标从内部div移动到周围页面时,会触发两个鼠标移出事件,因为当鼠标从内部移动到外部时,事件会触发一次,然后再从外部移动到周围页面时再次触发。

我知道可以使用ev.stopPropagation()取消事件,所以我尝试注册一个事件处理程序来取消事件传播。但是,这不会阻止鼠标从外部div移动到内部div时触发事件。

因此,除非我忽略了什么,否则我认为这种行为无法在不使用复杂的鼠标跟踪函数的情况下实现。将来,我计划使用更先进的框架(如jQuery)重新实现大量代码,但目前,我想知道是否有一种简单的方法在常规JavaScript中实现上述行为。


页面是否将元素视为组合?例如,外部div本身只是“outer-div”,然后内部的div在其中将被视为“outer-div+inner-div”,因此如果您在它们之间切换,则会将它们视为两个单独的元素,都附有onmouseout事件?这似乎有点奇怪,但这似乎是这里页面的工作方式。 - animuson
1个回答

6

mouseout事件会从内部div“冒泡”到外部div。如果要从外部div检测到这一点,请检查eventtarget属性:

<div id="outer">
    <div id="inner">x</div>
</div>

document.getElementById('outer').onmouseout= function(event) {
    // deal with IE nonsense
    if (event===undefined) event= window.event;
    var target= 'target' in event? event.target : event.srcElement;

    if (target!==this) return;
    ...
};

mouseout事件通常的问题是,即使鼠标指针只是移动到子元素中,也会在其移动“出”父元素时触发。您可以手动检测此情况,方法是查找鼠标正在移动到的元素的祖先列表:

    var other= 'relatedTarget' in event? event.relatedTarget : event.toElement;
    while ((other= other.parentNode).nodeType===1)
        if (other===this) return;

这是mousein/mouseout模型:它只关心鼠标的直接父元素是哪个。更常用的是mouseenter/mouseleave模型,该模型将元素树作为一个整体进行考虑,因此只有在指针离开元素或其后代而不是直接进入元素或其后代时才会收到mouseleave事件。

不幸的是,mouseenter/mouseleave目前只是Internet Explorer浏览器的一对事件。希望其他浏览器也能支持它,因为这被期望成为DOM Level 3事件的一部分。


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