You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何实现鼠标离开导航栏菜单及下拉框时隐藏下拉框?

嘿,我来帮你搞定这个导航栏下拉框的问题!先把那几个鼠标事件的区别讲清楚,再给你调整代码实现你要的效果——鼠标离开菜单项或者下拉框时自动隐藏下拉。

先搞懂鼠标事件的核心区别

你用到的几个事件其实有明确的分工,搞明白就不会乱了:

  • hover():这是jQuery的快捷方法,本质是mouseentermouseleave的组合。如果只传一个函数,它只会在鼠标进入元素时触发;只有传两个函数时,第二个才会在鼠标离开时执行。你现在只写了进入的逻辑,所以离开时下拉框不会隐藏,这是核心问题!
  • mouseenter:鼠标进入元素本身(不包括子元素)时触发,不会冒泡。比如鼠标从导航项移到它的下拉框(子元素),不会再次触发这个事件。
  • mouseleave:鼠标离开元素本身(不包括子元素)时触发,同样不冒泡。和mouseenter配对使用,处理下拉菜单非常合适,不会因为鼠标在下拉框内移动就频繁触发事件。

对比一下mouseover/mouseout,这两个会冒泡,鼠标在子元素间移动时会反复触发,所以处理下拉菜单优先选mouseenter/mouseleave

你的代码问题分析

你现在把.navbar-menu-each.submenu-dropdown都绑定了hover,但只写了进入逻辑,没处理离开;而且这种分开绑定的方式容易出现冲突——比如鼠标离开导航项但还在下拉框时,可能触发错误的隐藏逻辑。

更好的思路是:把导航项和下拉框放在同一个父容器里,然后给父容器绑定mouseentermouseleave。这样鼠标只要在父容器范围内(不管是导航项还是下拉框),下拉框就保持显示;一旦离开整个父容器,就自动隐藏。

修改后的完整代码方案

首先调整你的HTML结构(确保导航项和下拉框有共同的父容器):

<div class="navbar-menu-item-container">
  <div class="navbar-menu-each" data-menu-choice="0">
    <a href="#">Employee Management</a>
  </div>
  <!-- 其他导航项同理,设置对应的data-menu-choice值 -->
  <div class="navbar-menu-each" data-menu-choice="1">
    <a href="#">Memo Management</a>
  </div>
  <!-- ... 更多导航项 ... -->
  <div class="submenu-dropdown"></div>
</div>

然后修改JavaScript代码,优化逻辑并添加隐藏处理:

// 鼠标进入导航项时,渲染下拉内容并显示
$(".navbar-menu-each").mouseenter(function() {
  const $currentMenu = $(this);
  const menuChoice = parseInt($currentMenu.data("menu-choice")); // 用data属性传递菜单标识,比val()更合理
  const menuPosition = $currentMenu.find("a").position();
  let dropdownContent = "";

  // 根据菜单选项生成下拉内容,用模板字符串更易读
  switch(menuChoice) {
    case 0:
      dropdownContent = `
        <li class='submenu-dropdown-each'>New Employee Registration</li>
        <li class='submenu-dropdown-each submenu-selected'>Employee List</li>
        <li class='submenu-dropdown-each'>Employee Rehire</li>
        <li class='submenu-dropdown-each'>Employee Without Bank Account</li>
        <li class='submenu-dropdown-each'>Employee Without PPh 21</li>
      `;
      break;
    case 1:
      dropdownContent = `
        <li class='submenu-dropdown-each'>Memo Template</li>
        <li class='submenu-dropdown-each'>Print Memo</li>
      `;
      break;
    case 2:
      dropdownContent = `
        <li class='submenu-dropdown-each'>Download & Upload</li>
        <li class='submenu-dropdown-each'>Send Email</li>
      `;
      break;
    case 3:
      dropdownContent = `
        <li class='submenu-dropdown-each'>Employee Data Approvals</li>
        <li class='submenu-dropdown-each'>Employment Status Undo</li>
      `;
      break;
    case 4:
      dropdownContent = `
        <li class='submenu-dropdown-each'>Employee Data Report</li>
        <li class='submenu-dropdown-each'>Headcount Report</li>
        <li class='submenu-dropdown-each'>Employee Recapitulation Report</li>
      `;
      break;
  }

  // 填充下拉内容并计算位置
  const $dropdown = $(".submenu-dropdown");
  $dropdown.html(dropdownContent);
  
  const dropdownWidth = $dropdown.width();
  const rightEdge = $(document).width();
  let dropdownLeft = menuPosition.left;

  // 调整位置,避免下拉框超出屏幕
  if ((dropdownLeft + dropdownWidth) >= (rightEdge - 16)) {
    dropdownLeft = rightEdge - dropdownWidth - 16;
  } else if (dropdownLeft <= 16) {
    dropdownLeft = 16;
  }

  $dropdown.css({"left": `${dropdownLeft}px`}).show();

  // 高亮当前选中的导航项
  $(".navbar-menu-each").removeClass("menu-on");
  $currentMenu.addClass("menu-on");
});

// 鼠标离开整个导航容器时,隐藏下拉框
$(".navbar-menu-item-container").mouseleave(function() {
  $(".submenu-dropdown").hide();
  // 可选:如果需要离开后取消导航项高亮,就打开下面的注释
  // $(".navbar-menu-each").removeClass("menu-on");
});

// 保留点击导航项的高亮逻辑(如果需要)
$(".navbar-menu-each").click(function() {
  $(".navbar-menu-each").removeClass("menu-on");
  $(this).addClass("menu-on");
});

补充你的CSS(完善下拉框的关键样式,你原来的CSS没写完这部分):

/* 导航容器:让下拉框相对于它定位 */
.navbar-menu-item-container {
  position: relative;
  display: inline-block;
}

/* 下拉框样式 */
.submenu-dropdown {
  position: absolute;
  top: 100%; /* 固定在导航项下方 */
  left: 0;
  background-color: #fff;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
  display: none; /* 默认隐藏 */
  padding: 8px 0;
  min-width: 220px;
  z-index: 100;
}

.submenu-dropdown-each {
  padding: 8px 16px;
  cursor: pointer;
  font-size: 13px;
}

.submenu-dropdown-each:hover {
  background-color: #f5f5f5;
}

.submenu-selected {
  background-color: #e8f4f8;
  color: #007bff;
}

/* 你的原有CSS可以保留,这里只补充关键部分 */
.navbar-menu-each {
  padding-left: 32px;
  padding-right: 32px;
  display: inline-block;
  /* 原有样式... */
}

.navbar-menu-each.menu-on {
  /* 你的高亮样式,比如改变文字颜色或下划线 */
  color: #007bff;
  border-bottom: 2px solid #007bff;
}
关键优化点
  1. data-menu-choice属性代替val():导航项不是表单元素,用data属性传递标识更合理。
  2. 父容器绑定mouseleave:确保鼠标在导航项或下拉框内时,下拉框都保持显示;离开整个容器才隐藏,完美解决你的需求。
  3. 模板字符串替代HTML拼接:比你原来的&lt;这种转义写法可读性高太多,维护起来更轻松。
  4. 定位逻辑优化:确保下拉框不会超出屏幕边界,提升用户体验。

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

火山引擎 最新活动