
小屏幕下嵌套下拉菜单无法逐层点击展开,根本原因在于 JavaScript 事件监听仅作用于 .submenu,而深层菜单使用的是 .nested-menu 类,导致点击子项时无响应;需统一处理各级菜单的显隐逻辑并阻止事件冒泡干扰。
小屏幕下嵌套下拉菜单无法逐层点击展开,根本原因在于 javascript 事件监听仅作用于 `.submenu`,而深层菜单使用的是 `.nested-menu` 类,导致点击子项时无响应;需统一处理各级菜单的显隐逻辑并阻止事件冒泡干扰。
在响应式导航菜单中,为兼顾大屏(hover 触发)与小屏(click 触发)体验,常采用媒体查询 + JavaScript 的混合方案。但原代码存在一个关键缺陷:事件监听器只绑定在顶层 .menu-item 上,且仅查找 .submenu 元素进行显隐切换,完全忽略了 .nested-menu 这一深层结构。因此,点击“Chocolate Cake”时,menuItem.querySelector(".submenu") 返回 null(因为该元素下直接包含的是 .nested-menu),后续逻辑失效,深层菜单自然无法展开。
✅ 正确解法:递归式菜单切换逻辑
我们应将「点击触发显隐」的逻辑泛化为对任意含子菜单的 <li> 元素生效,无论其子菜单是 .submenu 还是 .nested-menu。同时,必须严格控制事件冒泡,避免点击子菜单时意外触发父级关闭。
以下是优化后的核心 JavaScript(替换原 <script> 内容):
<script>
// 统一处理所有可展开菜单项(支持 .submenu 和 .nested-menu)
function setupMenuToggle() {
if (window.innerWidth > 768) return; // 仅在小屏启用
const menuItems = document.querySelectorAll('.menu-item');
menuItems.forEach(item => {
item.addEventListener('click', function (e) {
e.stopPropagation(); // 阻止冒泡,防止触发 document 点击关闭
// 查找当前项下的任意一级子菜单(.submenu 或 .nested-menu)
const submenu = this.querySelector('.submenu, .nested-menu');
if (!submenu) return;
// 切换该子菜单的显示状态
submenu.style.display = submenu.style.display === 'block' ? 'none' : 'block';
});
});
// 点击菜单外部区域,关闭所有子菜单
document.addEventListener('click', function (e) {
if (window.innerWidth <= 768) {
const isClickInsideMenu = e.target.closest('.menu-item');
if (!isClickInsideMenu) {
document.querySelectorAll('.submenu, .nested-menu').forEach(el => {
el.style.display = 'none';
});
}
}
});
}
// 初始化 + 响应窗口缩放
setupMenuToggle();
window.addEventListener('resize', setupMenuToggle);
</script>? 同时需补充的 CSS 适配
为确保小屏下 .nested-menu 能被正确定位和显示,请微调 CSS(在原有样式后追加):
/* 小屏下确保 nested-menu 可见且定位正确 */
@media screen and (max-width: 768px) {
.submenu, .nested-menu {
position: static; /* 改为 static,避免绝对定位在小屏下错位 */
display: none;
background-color: #444;
margin-top: 5px;
}
.submenu li, .nested-menu li {
padding: 8px 12px;
}
.submenu li a, .nested-menu li a {
padding: 6px 10px;
}
}⚠️ 注意事项与最佳实践
- 不要混用 :hover 与 click 逻辑:大屏用 @media (min-width: 769px) 启用 hover 效果,小屏完全交由 JS 控制,二者 CSS 规则需严格隔离,避免冲突;
- 禁止对 <a> 标签默认行为做 preventDefault():本例中链接可正常跳转,若需纯展开(不跳转),请给 <a> 添加 href="javascript:void(0)" 或监听后 e.preventDefault();
- 移动端点击穿透风险:iOS Safari 对快速连续点击有延迟,如需更高可靠性,可引入 touchstart 事件替代 click,或使用 fastclick 库;
- 无障碍支持:建议为可展开项添加 aria-expanded 属性,并在 JS 中同步更新,提升屏幕阅读器兼容性。
通过上述重构,菜单层级不再受限于类名深度——无论是二级 .submenu 还是三级 .nested-menu,只要结构符合 <li class="menu-item"> → <ul class="submenu|nested-menu"> 模式,点击即可逐层展开/收起,真正实现语义清晰、健壮可维护的响应式嵌套导航。

















