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

页面嵌套菜单点击子链接后子菜单消失,如何用JS实现持续显示?

嘿,这个问题我之前做项目时也遇到过,其实核心就是子链接的点击事件冒泡到父元素,触发了父菜单的收起逻辑,用几行JavaScript就能轻松解决。我给你整理了一个完整的、可直接复用的方案:

1. 先确认基础菜单结构(示例)

假设你的菜单HTML是类似这样的嵌套结构:

<ul class="menu">
  <li class="menu-item has-children">
    <a href="#" class="menu-link">父菜单1</a>
    <ul class="submenu">
      <li class="submenu-item">
        <a href="/page1" class="submenu-link">子菜单1-1</a>
      </li>
      <li class="submenu-item">
        <a href="/page2" class="submenu-link">子菜单1-2</a>
      </li>
    </ul>
  </li>
  <li class="menu-item has-children">
    <a href="#" class="menu-link">父菜单2</a>
    <ul class="submenu">
      <li class="submenu-item">
        <a href="/page3" class="submenu-link">子菜单2-1</a>
      </li>
    </ul>
  </li>
</ul>

2. 匹配你的CSS逻辑

这部分和你现有的设置一致,子菜单默认隐藏,父菜单激活时显示:

/* 子菜单默认隐藏 */
.submenu {
  display: none;
}

/* 父菜单激活时显示子菜单 */
.has-children.is-active .submenu {
  display: block;
}

/* 激活链接的高亮样式 */
.menu-link.is-active,
.submenu-link.is-active {
  color: #ff4400;
  font-weight: bold;
  /* 可根据需求添加其他样式 */
}

3. 核心JavaScript解决方案

这段代码做了三件关键的事:控制父菜单展开/收起、阻止子链接事件冒泡、管理激活类的状态:

// 获取所有带子菜单的父链接
const parentLinks = document.querySelectorAll('.menu-item.has-children .menu-link');
// 获取所有子菜单链接
const childLinks = document.querySelectorAll('.submenu-link');

// 处理父菜单点击:切换子菜单显示/隐藏
parentLinks.forEach(link => {
  link.addEventListener('click', function(e) {
    // 如果父链接是占位的#,阻止默认跳转行为
    e.preventDefault();
    // 找到当前父菜单的容器
    const parentItem = this.closest('.menu-item.has-children');
    
    // 切换父菜单的激活状态,控制子菜单显示
    parentItem.classList.toggle('is-active');
    
    // 可选:同时只展开一个父菜单(展开当前的,收起其他的)
    parentLinks.forEach(otherLink => {
      const otherItem = otherLink.closest('.menu-item.has-children');
      if (otherItem !== parentItem) {
        otherItem.classList.remove('is-active');
      }
    });
  });
});

// 处理子菜单点击:保持子菜单可见
childLinks.forEach(link => {
  link.addEventListener('click', function(e) {
    // 核心!阻止事件冒泡到父元素,避免触发父菜单的收起逻辑
    e.stopPropagation();
    
    // 移除所有链接的激活状态,避免多个高亮
    document.querySelectorAll('.menu-link.is-active, .submenu-link.is-active').forEach(activeLink => {
      activeLink.classList.remove('is-active');
    });
    
    // 给当前点击的子链接添加激活类
    this.classList.add('is-active');
    
    // 保险:强制父菜单保持激活状态(防止意外收起)
    const parentItem = this.closest('.menu-item.has-children');
    parentItem.classList.add('is-active');
  });
});

关键说明

  • e.stopPropagation()是解决问题的核心:它阻止了子链接的点击事件向上传递到父菜单元素,这样父菜单的收起逻辑就不会被误触发,子菜单就能一直保持显示。
  • 如果你的父链接是实际的跳转链接(不是#),可以去掉e.preventDefault(),或者调整逻辑让点击父链接先展开子菜单,再根据需求处理跳转。
  • 如果你不需要“同时只展开一个菜单”的功能,删掉父菜单点击事件里的parentLinks.forEach(otherLink => {...})这段代码即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 11:19:36