mouseEnter 和 mouseOver 的区别

理解 mouseenter 和 mouseover 事件在冒泡和触发时机上的差异

问题

mouseentermouseover 有什么区别?

解答

mouseentermouseover 都用于处理鼠标进入元素的事件,但在冒泡行为和触发时机上有本质区别。

事件冒泡

mouseenter:不会冒泡。鼠标进入元素时只在该元素上触发一次,不会传播到父元素。

mouseover:会冒泡。鼠标进入元素或其子元素时都会触发,并向上冒泡到父元素。

const parent = document.querySelector('.parent');
const child = document.querySelector('.child');

parent.addEventListener('mouseenter', () => {
  console.log('mouseenter: 只在进入 parent 时触发一次');
});

parent.addEventListener('mouseover', () => {
  console.log('mouseover: 进入 parent 或 child 时都会触发');
});

触发范围

mouseenter:只在鼠标首次进入目标元素时触发,鼠标在子元素间移动不会重复触发。

mouseover:鼠标进入目标元素或其任何子元素时都会触发。鼠标在子元素间移动会导致父元素多次触发事件。

<div class="parent">
  <div class="child1">Child 1</div>
  <div class="child2">Child 2</div>
</div>
// mouseenter: 鼠标从 child1 移到 child2,parent 不会再次触发
// mouseover: 鼠标从 child1 移到 child2,parent 会再次触发

relatedTarget 属性

两个事件的 relatedTarget 都指向鼠标移动前所在的元素,但使用场景不同:

element.addEventListener('mouseenter', (e) => {
  console.log('从', e.relatedTarget, '进入', e.target);
});

element.addEventListener('mouseover', (e) => {
  console.log('从', e.relatedTarget, '移动到', e.target);
});

使用场景

mouseenter 适合检测鼠标首次进入元素的行为,如显示提示框:

tooltip.addEventListener('mouseenter', () => {
  showTooltip();
});

mouseover 适合需要监听子元素的场景,如事件委托:

list.addEventListener('mouseover', (e) => {
  if (e.target.matches('li')) {
    highlightItem(e.target);
  }
});

关键点

  • mouseenter 不冒泡,只在鼠标首次进入元素时触发一次
  • mouseover 会冒泡,鼠标进入元素或子元素时都会触发
  • mouseenter 适合简单的悬停效果,避免子元素干扰
  • mouseover 适合需要事件委托或监听子元素的场景
  • 两者都有对应的离开事件:mouseleavemouseout