愿你坚持不懈,努力进步,进阶成自己理想的人

—— 2017.09, 写给3年后的自己

详解mouseenter和mouseover区别

mouseentermouseover是两个常用的鼠标事件。所以很有必要区分清楚两个事件的区别

一、表象

大多数材料对于mouseentermouseover的区别解释为:
1)mouseover 不仅会在元素本身触发,也会在其子元素中触发
2)mouseenter 只会在元素本身触发,不会在子元素中触发
实验代码:

<div id="overParent" style="padding: 20px; background: #555">
    <div id="overChild" style="padding: 20px; background: #FFF">
        Mouseover
    </div>
</div>

<div id="enterParent" style="padding: 20px; margin-top: 20px; background: #555">
    <div id="enterChild" style="padding: 20px; background: #FFF">
        Mouseenter
    </div>
</div>

JS部分:

const overParent = document.getElementById('overParent');
const enterParent = document.getElementById('enterParent');

overParent.addEventListener('mouseover', function() {
    console.log('Mouseover');
});
enterParent.addEventListener('mouseenter', function() {
    console.log('Mouseenter');
});


我们会发现:
1)在mouseover中,当我们把鼠标从外面移入黑框的时候,会输出Mouseover,而从黑框移入白框的时候,也会输出Mouseover
2)在mouseenter中,当我们把鼠标从外面移入黑框的时候,会输出Mouseenter,而从黑框移入白框的时候,不会输出Mouseenter
这也就是说,上面的结论得到了证实。mouseenter的事件,不会在子元素中触发。


二、原理

但是,为什么呢??总觉得还没有理解深入

于是,通过MDN文档,我们可以找到关于mouseovermouseenter的区别说明:
https://developer.mozilla.org/en-US/docs/Web/Events/mouseenter

解释如下:
当指针设备(通常为鼠标)移到绑有事件监听器的元素上方时,mouseenter事件会被触发。和mouseover相似,但是不同的在于mouseenter不会冒泡,并且当鼠标从它的一个子节点的位置移到它自身的位置时,不会触发mouseenter


当进入一个元素的时候,mouseenter事件会发送给它层级上面的每一个元素(一起发送的)。如图所示,当我们鼠标移入Text的时候,它上面的4个层级中都会触发mouseenter事件


mouseover事件呢,它会从触发节点开始找到DOM树中最深层次的元素,然后从从这个元素开始冒泡传递上去,直到被组织冒泡或者达到根节点

于是,有了这个解释后,表象中的两点就很容易解释了:
1)当鼠标从外面移入黑框的时候,会找到最内层的节点(这里是div#overChild),然后开始冒泡,之后mouseover事件就传到了div#overParent中,从而触发了div#overParent中绑定的event handler。如果这么解释还不足以说明的话,那么可以实验如:

const overChild = document.getElementById('overChild');
overChild.addEventListener('mouseover', function(event) {
    event.stopPropagation();
});

这时候,当我们鼠标从黑框移入白框的时候,就不会输出Mouseover了,因为在子元素中的冒泡被阻止了,传不到父元素,所以div#overParent拿不到这个事件。
2)当鼠标从外面框移入黑框的时候,只会触发div#enterParent上的mouseenter事件,子元素中不会触发,所以从黑框移入白框,不会输出Mouseenter。但是这种情况下,div#enterParent所在层级上面的祖先节点,都会收到mouseenter事件


三、性能方面的注意点

由于mouseenter的性质,所以在深层次的层级结构中,mouseenter事件的发送量将会是相当大的,会因此导致显著的性能问题。在这种情况下,更好的方式是监听mouseover事件。


四、其他

mouseenter可以和与其行为对称的mouseleave事件结合使用,那么mouseenter就会以一个类似于CSS中:hover伪类选择器的方式起作用