使用querySelectorAll绑定下拉菜单事件无法触发对应子菜单
问题根因
两次代码失效都是DOM选择逻辑错误导致的:
- 最初使用
document.querySelector()获取元素时,该API只会返回匹配选择器的第一个DOM节点:- 第一次只拿到了第一个
.dropdown元素绑定点击事件,第二个下拉根本没绑定监听器,点击自然无响应 - 后续即使遍历绑定了所有下拉的事件,你依然用
document.querySelector('.submenu')全局查找子菜单,这个语句永远只会返回页面里第一个.submenu节点,所以不管点哪个下拉,操作的都是第一个子菜单,完全匹配不到第二个下拉的子元素
- 第一次只拿到了第一个
- 核心逻辑漏洞:没有建立「当前点击的下拉项」和「对应子菜单」的关联,全局查找子菜单的逻辑必然会出现操作串位的问题。
修正方案
绑定事件时不要全局查找子菜单,要在当前被点击的下拉元素内部查找对应的子菜单,才能精准控制对应项的显隐,完整可运行代码如下:
// 获取所有下拉菜单项 const mobileDropdowns = document.querySelectorAll(".dropdown"); mobileDropdowns.forEach(dropdown => { dropdown.addEventListener('click', (e) => { // 阻止a标签默认跳转、锚点滚动的默认行为 e.preventDefault(); // 仅在当前点击的下拉容器内部查找对应的子菜单 const currentSubmenu = dropdown.querySelector('.submenu'); currentSubmenu.classList.toggle('hidden'); // 可选优化:实现手风琴效果,点开当前项时自动收起其他已展开的子菜单 mobileDropdowns.forEach(otherItem => { if (otherItem !== dropdown) { otherItem.querySelector('.submenu').classList.add('hidden'); } }) }) })
原有导航DOM结构不需要做任何调整,只要保持每个.dropdown容器内部包含自己的.submenu子元素,上述代码就能正常工作,不会出现点击无响应、操作串位的问题。
内容的提问来源于stack exchange,提问作者AvraSys
相关产品推荐
相关产品推荐

