如何用原生JavaScript实现移动端导航子菜单切换并关闭其他展开菜单
移动端导航菜单实现方案
需求:
- 点击父菜单项时,切换其内部
.sub-menu的active类以显示/隐藏子菜单 - 打开新子菜单时,自动关闭其他已展开的子菜单
- 默认状态下子菜单隐藏,仅添加
active类后显示
原代码逻辑缺失关闭其他子菜单的处理,以下是完善后的实现:
完善后的JavaScript代码
// 获取所有父菜单项 const parentItems = document.querySelectorAll('#menu-mobile .main-wrap ul > li'); parentItems.forEach(item => { item.addEventListener('click', (e) => { // 若点击的是子菜单内的元素,不触发父菜单逻辑 if (e.target.closest('.sub-menu')) return; e.preventDefault(); // 获取当前父菜单的子菜单 const currentSubMenu = item.querySelector('.sub-menu'); if (!currentSubMenu) return; // 没有子菜单的项直接返回 // 关闭所有其他已激活的子菜单 document.querySelectorAll('#menu-mobile .sub-menu.active').forEach(subMenu => { if (subMenu !== currentSubMenu) { subMenu.classList.remove('active'); } }); // 切换当前子菜单的激活状态 currentSubMenu.classList.toggle('active'); }); });
CSS代码(保留原显示逻辑)
#menu-mobile { position: fixed; top: 100px; overflow: auto; display: block; height: calc(100vh - 70px); width: 200px; right: 0; } #menu-mobile .main-wrap { overflow: hidden; margin: 0; min-height: calc(10vh); position: relative; } #menu-mobile .main-wrap ul > li { list-style: none; width: 100%; display: inline-block; padding-left: 15px; margin: 0; min-height: 50px; line-height: 50px; border-bottom: 1px solid #000; } #menu-mobile .main-wrap ul > li ul { display: none; opacity: 0; background-color: #333333; transition: opacity 0.25s ease; border-top: 1px solid #000000; } #menu-mobile .main-wrap ul > li ul.active { display: block; opacity: 1; }
HTML代码(修正重复ID问题)
<div id="menu-mobile"> <div class="main-wrap"> <ul id="menu-mobile-menu"> <li id="menu-item-12800"> <a href="www.google.com">Menu Item 1</a> <ul class="sub-menu"> <li id="menu-item-1263" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-1263"> <a href="www.google.com">Sub Menu Item 1</a> </li> </ul> </li> <li id="menu-item-12801"> <a href="www.google.com">Menu Item 2</a> <ul class="sub-menu"> <li id="menu-item-1264" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-1264"> <a href="www.google.com">Sub Menu Item 2</a> </li> </ul> </li> </ul> </div> </div>
核心逻辑说明
- 点击范围过滤:避免点击子菜单内元素时误触发父菜单的折叠/展开操作
- 全局子菜单管理:切换当前子菜单前,自动关闭所有其他已激活的子菜单
- 容错处理:判断当前父菜单是否存在子菜单,避免无菜单项时出现报错
- HTML规范修正:修复原代码中重复ID的问题(页面ID必须唯一)
内容的提问来源于stack exchange,提问作者Mrich
相关产品推荐
相关产品推荐

