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

如何用纯JS实现鼠标移出div后保留ul li标签的hover类

问题根因

你的代码核心问题出在两个地方:

  1. 将mouseover事件绑定到了全局document对象,鼠标在页面任意位置移动都会触发处理函数。当鼠标移出下拉容器后,事件触发源e.target不再是下拉选项li,处理函数会直接把非li元素设为激活对象,原有选中li的hover类就会被移除。
  2. 没有对事件触发源做有效性校验,非上下方向键触发时,不管当前触发元素是不是下拉选项,都会直接替换激活对象。

修复后的完整代码

JavaScript部分

// 先获取下拉容器和所有选项元素
const dropdownContainer = document.querySelector('.dropdown-test');
const dropdownItems = document.querySelectorAll('.dropdownItemContainer li');
// 初始化激活项
let active = document.querySelector(".hover") || dropdownItems[0];

// 只给下拉选项绑定mouseover事件,不要绑定全局
dropdownItems.forEach(item => {
  item.addEventListener('mouseover', handler);
});
// 方向键事件绑定到下拉容器,保证只有容器聚焦时才响应,避免和页面其他快捷键冲突
dropdownContainer.addEventListener('keydown', handler);
// 给容器加tabindex使其可以聚焦,支持键盘操作
dropdownContainer.setAttribute('tabindex', '-1');

function handler(e){
  // 先存旧的激活项
  const oldActive = active;
  if (e.type === 'keydown') {
    // 用e.key替代废弃的e.which,兼容性更好
    if (e.key === 'ArrowDown') {
      // 向下选,没有下一个就停在最后一个
      active = active.nextElementSibling || dropdownItems[dropdownItems.length - 1];
      // 阻止页面默认滚动行为
      e.preventDefault();
    } else if (e.key === 'ArrowUp') {
      // 向上选,没有上一个就停在第一个
      active = active.previousElementSibling || dropdownItems[0];
      e.preventDefault();
    }
    // 优化:选中项自动滚动到可视区域,适配可滚动下拉场景
    active.scrollIntoView({ block: 'nearest' });
  } else if (e.type === 'mouseover') {
    // 只有鼠标悬停在选项上时,才把当前li设为激活项
    active = e.target;
  }
  // 只有激活项真的变了才修改类,减少不必要的DOM操作
  if (oldActive !== active) {
    oldActive.classList.remove('hover');
    active.classList.add('hover');
  }
}

原有CSS和HTML不需要改动,保持你原来的写法即可。

核心逻辑说明

  • 事件绑定范围限制:把鼠标悬停事件只绑定给下拉选项li,鼠标移出下拉区域后不会触发相关逻辑,自然不会修改激活项的类名,实现选中状态稳定保留。
  • 事件类型区分处理:键盘事件和鼠标事件分开判断,只有对应的合法操作才会修改激活项,避免误触发。
  • 激活项有效性保证:所有修改激活项的逻辑都限定在下拉选项的范围内,不会出现激活项变成非li元素的情况。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 08:45:03