如何用事件监听器实现仅展开对应UL的原生JS下拉菜单?
实现点击对应UL标题仅展开当前下拉菜单
问题说明
尝试用JavaScript创建下拉菜单,需求是点击每个UL的第一个子元素时,仅展开该UL下的子元素,但当前点击“Our Company”或“Our Products”时,所有UL下的元素都会被显示,且只有第一个主标题能触发事件。
原代码
HTML结构
<div class="menu_wrapper"> <ul class="menu_company"> <li class="main_item company">Our Company</li> <li class="menu_item hide_menu">About US</li> <li class="menu_item hide_menu">Our offices</li> <li class="menu_item hide_menu">Careers</li> </ul> <ul class="products"> <li class="main_item products">Our Products</li> <li class="menu_item hide_menu">Product A</li> <li class="menu_item hide_menu">Product B</li> <li class="menu_item hide_menu">Communication</li> </ul> </div>
原JavaScript代码
const hideMenus = document.querySelectorAll('.hide_menu') const manageMenu = (() => { const displayMenus = () => { hideMenus.forEach((menu) => { menu.classList.toggle('hide_menu') }) } })() const mainItem = document.querySelector('.main_item') mainItem.addEventListener('click', () => { manageMenu.displayMenus() })
问题原因
document.querySelector('.main_item')仅选中第一个主标题,导致第二个“Our Products”点击无响应;hideMenus获取了全局所有.hide_menu元素,执行切换操作时会影响所有下拉项,而非当前点击的UL下的元素。
解决方案
修改JavaScript代码,针对每个主标题绑定点击事件,并仅操作当前主标题所在UL下的子元素:
// 获取所有主标题元素 const mainItems = document.querySelectorAll('.main_item') // 遍历绑定每个主标题的点击事件 mainItems.forEach(item => { item.addEventListener('click', () => { // 定位当前点击项的父级UL const parentUl = item.parentElement // 仅获取当前UL下的下拉子元素 const subMenus = parentUl.querySelectorAll('.hide_menu') // 切换当前UL下子元素的显示状态 subMenus.forEach(menu => { menu.classList.toggle('hide_menu') }) }) })
优化说明
- 去掉冗余的闭包封装,直接在事件回调中处理逻辑更简洁;
- 通过
parentElement精准定位当前操作的UL范围,避免影响其他下拉菜单; - 选中所有主标题元素,确保每个下拉菜单的标题都能触发对应操作。
内容的提问来源于stack exchange,提问作者user3741299
相关产品推荐
相关产品推荐

