导航菜单点击多动作异常:二次点击无法关闭子菜单求助
导航菜单展开/折叠功能修复
我的导航有3个带二级菜单的父菜单,点击父菜单或加减号图标需要实现两类操作:
第一类操作(点击未展开的菜单)
- 显示当前父菜单的子菜单
- 将当前菜单的加号切换为减号
- 关闭其他所有已展开的子菜单
- 将其他菜单的减号切换为加号
第二类操作(点击已展开的菜单)
- 关闭当前父菜单的子菜单
- 将当前菜单的减号切换为加号
目前我的jQuery代码能实现第一类操作,但第二类操作无法生效,求解决。
原代码
HTML
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script> <ul> <li class="non-active"> <a class="non-active parent-list" href="#level1">level 1</a> <div class="plus-minus icon-plus"> </div> </li> <ul class="child-layer collapse"> <li>Sub Child 1</li> <li>Sub Child 1</li> <li>Sub Child 1</li> </ul> <li class="non-active"> <a class="non-active parent-list" href="#level2">level 2</a> <div class="plus-minus icon-plus"> </div> </li> <ul class="child-layer collapse"> <li>Sub Child 2</li> <li>Sub Child 2</li> <li>Sub Child 2</li> </ul> <li class="non-active"> <a class="non-active parent-list" href="#level3">level 3</a> <div class="plus-minus icon-plus"> </div> </li> <ul class="child-layer collapse"> <li>Sub Child 3</li> <li>Sub Child 3</li> <li>Sub Child 3</li> </ul> </ul>
CSS
li { display: flex } .icon-plus:before { content: "\2795"; } .icon-minus:before { content: "\2212"; } .parent-list { padding-right: 50px; cursor: pointer; } .collapse { display: none; } .show { display: block; }
jQuery
$(function(showHidesubMenu) { $('.parent-list').click(function() { $(this) .toggleClass('open').next().toggleClass('icon-minus icon-plus') .add($('.parent-list.open').not(this).removeClass('open').next().toggleClass('icon-minus icon-plus')) .parent().next('.child-layer').toggleClass('show') }) }) $(function() { $('.plus-minus').click(function() { $(this) .prev().toggleClass('open') .next().toggleClass('icon-minus icon-plus') .add($('.parent-list.open').not(this).removeClass('open')) .parent().next('.child-layer').toggleClass("show"); }) })
修复方案
问题原因
原代码逻辑混乱,处理当前元素时同时触发全局toggleClass导致状态冲突;两个点击事件逻辑重复,未明确判断菜单当前展开状态,无法执行正确的折叠操作。
修复后的jQuery代码
$(function() { // 统一处理父菜单和加减号的点击事件 $('.parent-list, .plus-minus').click(function(e) { // 阻止a标签默认跳转行为 e.preventDefault(); // 定位当前操作对应的父菜单、图标和子菜单 let $parent = $(this).hasClass('parent-list') ? $(this) : $(this).prev('.parent-list'); let $icon = $(this).hasClass('plus-minus') ? $(this) : $(this).next('.plus-minus'); let $childLayer = $parent.parent().next('.child-layer'); let isOpen = $parent.hasClass('open'); // 先关闭所有其他已展开的菜单 $('.parent-list.open').not($parent).each(function() { $(this).removeClass('open'); $(this).next('.plus-minus').removeClass('icon-minus').addClass('icon-plus'); $(this).parent().next('.child-layer').removeClass('show').addClass('collapse'); }); // 根据当前状态处理展开/折叠 if (isOpen) { // 已展开,执行折叠 $parent.removeClass('open'); $icon.removeClass('icon-minus').addClass('icon-plus'); $childLayer.removeClass('show').addClass('collapse'); } else { // 未展开,执行展开 $parent.addClass('open'); $icon.removeClass('icon-plus').addClass('icon-minus'); $childLayer.removeClass('collapse').addClass('show'); } }); });
修复说明
- 合并事件:将父菜单和加减号的点击事件合并,避免重复逻辑和冲突
- 状态判断:先判断当前菜单是否已展开,再执行对应操作,逻辑更清晰
- 独立处理其他菜单:先统一关闭所有其他已展开的菜单,再处理当前菜单的状态
- 阻止默认跳转:给a标签添加
e.preventDefault(),避免点击时跳转到锚点
内容的提问来源于stack exchange,提问作者abcid d
相关产品推荐
相关产品推荐

