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

基于For Loop的Dropdown Menu:实现点击时自动关闭其他下拉菜单

问题

我用For Loop实现的下拉菜单存在两个问题:

  1. 点击菜单项后,菜单会保持展开状态直至再次点击
  2. 点击新菜单项时,其他已展开的下拉菜单无法自动关闭

我尝试使用forEach循环、querySelector和querySelectorAll来解决,但目前未成功。请问如何修改代码,实现点击新菜单项时自动关闭其他下拉菜单?


解决方案

核心逻辑是:点击任意菜单时先关闭所有已展开的菜单,再切换当前菜单状态;同时修复子菜单的绑定逻辑,避免仅操作第一个子菜单的问题。

修改后的完整JavaScript代码

// 选择所有菜单和子标题元素
const menus = document.querySelectorAll('.menu');
const subTitles = document.querySelectorAll('.sub-title');

// 绑定主菜单点击事件
menus.forEach(menu => {
  const menuContent = menu.querySelector('.item');
  
  menu.addEventListener('click', (e) => {
    e.stopPropagation();
    
    // 关闭所有其他展开的菜单
    menus.forEach(otherMenu => {
      if (otherMenu !== menu) {
        const otherContent = otherMenu.querySelector('.item');
        otherMenu.classList.remove('darkgrey');
        otherContent.classList.remove('show');
        // 同步关闭其他菜单的子菜单
        const otherSubItem = otherMenu.querySelector('.sub-item');
        const otherSubTitle = otherMenu.querySelector('.sub-title');
        if (otherSubItem) otherSubItem.classList.remove('present');
        if (otherSubTitle) otherSubTitle.classList.remove('clear');
      }
    });
    
    // 切换当前菜单的展开/收起状态
    menu.classList.toggle('darkgrey');
    menuContent.classList.toggle('show');
  });
});

// 绑定子菜单标题点击事件
subTitles.forEach(subTitle => {
  const subItem = subTitle.nextElementSibling;
  const parentMenu = subTitle.closest('.menu');
  const parentItem = subTitle.closest('.item');
  
  subTitle.addEventListener('click', (e) => {
    e.stopPropagation();
    // 切换子菜单显示状态
    subItem.classList.toggle('present');
    subTitle.classList.toggle('clear');
    // 确保父菜单保持展开
    parentMenu.classList.add('darkgrey');
    parentItem.classList.add('show');
  });
});

// 全局点击事件:点击菜单外区域关闭所有菜单
window.addEventListener('click', () => {
  menus.forEach(menu => {
    const menuContent = menu.querySelector('.item');
    menu.classList.remove('darkgrey');
    menuContent.classList.remove('show');
    // 关闭所有子菜单
    const subItem = menu.querySelector('.sub-item');
    const subTitle = menu.querySelector('.sub-title');
    if (subItem) subItem.classList.remove('present');
    if (subTitle) subTitle.classList.remove('clear');
  });
});

关键优化点

  • 用querySelectorAll替代getElementsByClassName,获取静态元素集合,避免动态集合的索引问题
  • 点击菜单时先遍历关闭所有其他菜单,实现菜单互斥展开
  • 子菜单事件绑定到每个子标题,通过closest方法定位父元素,避免硬编码索引导致的仅第一个子菜单生效问题
  • 添加e.stopPropagation()阻止事件冒泡,避免点击菜单/子菜单时触发全局关闭事件

说明

HTML和CSS代码无需修改,保持原有样式结构即可。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 20:58:10