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

移动端下拉菜单点击链接或外部区域无法关闭的问题求助

移动端菜单点击链接或外部区域自动关闭的实现方案

我需要实现点击下拉菜单中的任意链接,或是点击菜单区域外部时,菜单自动关闭。试过多种方法都没成功,作为前端新手卡壳了。以下是我目前的代码:

原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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 06:20:48