移动端下拉菜单点击链接或外部区域无法关闭的问题求助
移动端菜单点击链接或外部区域自动关闭的实现方案
我需要实现点击下拉菜单中的任意链接,或是点击菜单区域外部时,菜单自动关闭。试过多种方法都没成功,作为前端新手卡壳了。以下是我目前的代码:
原JavaScript代码
const btnMobile = document.getElementById('btn-mobile'); function toggleMenu(event) { if (event.type === 'touchstart') event.preventDefault(); const nav = document.getElementById('nav'); nav.classList.toggle('active'); const active = nav.classList.contains('active'); event.currentTarget.setAttribute('aria-expanded', active); if (active) { event.currentTarget.setAttribute('aria-label', 'Fechar Menu'); } else { event.currentTarget.setAttribute('aria-label', 'Abrir Menu'); } } btnMobile.addEventListener('click', toggleMenu); btnMobile.addEventListener('touchstart', toggleMenu);
原HTML代码
<!DOCTYPE html> <html lang="pt-br"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Menu Mobile</title> <link rel="stylesheet" href="menu.css"> </head> <body> <header id="header"> <a id="logo" href="">Menu</a> <nav id="nav"> <button aria-label="Abrir Menu" id="btn-mobile" aria-haspopup="true" aria-controls="menu" aria-expanded="false"> <span id="hamburger"></span> </button> <ul id="menu" role="menu"> <li><a href="#home_wrapper" class="menu-link">Home</a></li> <li><a href="#servico" class="menu-link">Serviços</a></li> <li><a href="#paginas" class="menu-link">Páginas</a></li> <li><a href="#projetos" class="menu-link">Projetos</a></li> <li><a href="#empresas" class="menu-link">Empresas</a></li> <li><a href="#cupcode" class="menu-link">Cupcode</a></li> <li><a href="#recursos" class="menu-link">Recursos</a></li> <li><a href="#contato" class="menu-link">Contato</a></li> </ul> </nav> </header> <script src="menu.js"></script> </body> </html>
修改后的JavaScript代码(实现需求)
const btnMobile = document.getElementById('btn-mobile'); const nav = document.getElementById('nav'); const menuLinks = document.querySelectorAll('.menu-link'); // 统一处理菜单关闭逻辑 function closeMenu() { nav.classList.remove('active'); btnMobile.setAttribute('aria-expanded', 'false'); btnMobile.setAttribute('aria-label', 'Abrir Menu'); } function toggleMenu(event) { if (event.type === 'touchstart') event.preventDefault(); nav.classList.toggle('active'); const active = nav.classList.contains('active'); btnMobile.setAttribute('aria-expanded', active); btnMobile.setAttribute('aria-label', active ? 'Fechar Menu' : 'Abrir Menu'); } // 菜单按钮的点击/触摸触发 btnMobile.addEventListener('click', toggleMenu); btnMobile.addEventListener('touchstart', toggleMenu); // 点击菜单内的任意链接,关闭菜单 menuLinks.forEach(link => { link.addEventListener('click', closeMenu); }); // 点击菜单区域外部时,关闭菜单 document.addEventListener('click', (event) => { // 检查点击目标是否不在导航容器内,且菜单处于激活状态 if (!nav.contains(event.target) && nav.classList.contains('active')) { closeMenu(); } });
关键逻辑说明
- 提取
closeMenu函数统一处理菜单关闭,避免重复代码,维护更方便 - 给所有
.menu-link绑定点击事件,点击任意菜单链接都会触发关闭 - 全局点击监听中,用
nav.contains(event.target)判断点击区域,确保点击菜单内部(按钮、链接、菜单容器)不会误关闭菜单 - 保持原有的无障碍属性(
aria-expanded、aria-label)更新,符合前端无障碍规范
内容的提问来源于stack exchange,提问作者Bruno Uasli
相关产品推荐
相关产品推荐

