You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JavaScript Mouseover事件异常:hover子菜单时主元素事件仍触发

问题分析与解决

1. 选择器div > ul > li:not(ul)为什么无效?

这个选择器完全起不到过滤作用——:not(ul)是用来排除本身是ul标签的元素,但你选中的目标都是li标签,li不可能是ul,所以这个选择器等价于div > ul > li,根本没法排除子菜单里的li。

如果要选中Element1-4这类顶级主元素li,直接用div > ul > li就足够了:它只会匹配div下直接子ul的直接子li,子菜单里的li嵌套在下级ul中,本来就不会被这个选择器选中。

2. 为什么hover子菜单也会触发事件?

核心原因是事件冒泡:mouseover事件会沿着DOM树向上传递,当你hover子菜单元素(比如2.1)时,它的mouseover事件会冒泡到父级的主元素li,触发你绑定在主元素上的事件监听器,所以看起来子菜单也触发了主元素的事件。

3. 解决方法

有两种简单可行的处理方式:

方式一:改用mouseenter事件

mouseenter和mouseover的核心区别是:mouseenter不会冒泡,只有当鼠标真正进入绑定事件的元素本身时才会触发,进入子元素不会触发父级的mouseenter事件。替换事件类型即可:

const mainItems = document.querySelectorAll('div > ul > li');
mainItems.forEach(item => {
  item.addEventListener('mouseenter', function() {
    console.log(this.textContent.trim());
  });
});

方式二:在mouseover事件里判断触发源

如果一定要用mouseover,可以在事件处理函数里对比event.target和event.currentTarget:

  • event.currentTarget是绑定事件的主元素li
  • event.target是实际触发事件的元素(可能是子菜单里的元素)

只有当两者相同时,才执行打印逻辑:

const mainItems = document.querySelectorAll('div > ul > li');
mainItems.forEach(item => {
  item.addEventListener('mouseover', function(event) {
    if (event.target === event.currentTarget) {
      console.log(this.textContent.trim());
    }
  });
});

内容的提问来源于stack exchange,提问作者shamalamadingdong

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 03:43:16