侧边栏菜单异常展开bug排查及修复方案
侧边栏菜单多展开问题修复
问题描述
使用HTML、CSS、Bootstrap和JavaScript开发的侧边栏菜单,正常交互逻辑如下:
- 点击「Student Management」时,展开其子菜单
- 点击「Invoicing Management」时,自动折叠「Student Management」并展开自身子菜单
但存在异常场景:当所有菜单处于关闭状态时,快速多次点击「Student Management」,再点击一次「Invoicing Management」,最后切回点击「Student Management」,会出现两个菜单同时展开的情况。
当前代码
HTML代码
<!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width, initial-scale=1"> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="description" content=""> <meta name="author" content=""> <title>SMS_Online</title> <link href="//maxcdn.bootstrapcdn.com/bootstrap/4.1.1/css/bootstrap.min.css" rel="stylesheet" id="bootstrap-css"> <script src="//maxcdn.bootstrapcdn.com/bootstrap/4.1.1/js/bootstrap.min.js"></script> <script src="//cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script> <link href="//netdna.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css" rel="stylesheet" id="bootstrap-css"> <script src="//netdna.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js"></script> <script src="//code.jquery.com/jquery-1.11.1.min.js"></script> <link href="//maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css" rel="stylesheet"> </head> <body> <main role="main" class="container-fluid" style="padding:0px;"> <div class="col-xs-03"> <div class="sideMenu"> <div class="menuItems"> <ul class=""> <li class=""> <a href="#"> <i class="fa fa-dashboard fa-lg"></i>Main Dashboard<span class="arrow"></span> </a> </li> <li data-toggle="collapse" data-target="#studentsSubItems" class="collapsed"> <a href="#"> <i class="fas fa-user-graduate"></i>Student Management<i class="fas fa-chevron-down float-right sideMenuRightArrow"></i> </a> <ul class="sub-menu collapse" id="studentsSubItems"> <li> <a href="#"> <i class="fas fa-chevron-right"></i>Student Main </a> </li> <li> <a href="#"> <i class="fas fa-chevron-right"></i>Register Student </a> </li> </ul> </li> <li data-toggle="collapse" data-target="#invoicingSubItems" class="collapsed"> <a href="#"> <i class="fas fa-user-graduate"></i>Invoicing Management<i class="fas fa-chevron-down float-right sideMenuRightArrow"></i> </a> <ul class="sub-menu collapse" id="invoicingSubItems"> <li> <a href="#"> <i class="fas fa-chevron-right"></i>Invoicing Main </a> </li> <li> <a href="#"> <i class="fas fa-chevron-right"></i>Create an invoice </a> </li> </ul> </li> </ul> </div> </div> </div> </main> </body> </html>
CSS代码
.sideMenu { overflow: auto; font-family: verdana; font-size: 12px; font-weight: 200; background-color: #2e353d; width: 300px; height: 100vh; color: #e1ffff; } .sideMenu ul, #navbar ul, .sideMenu li, #navbar li { list-style: none; padding: 0px; margin: 0px; cursor: pointer; color: #e1ffff; } .sideMenu ul, .sideMenu li { line-height: 35px; } .sideMenuRightArrow { display: inline-block; padding-right: 10px; padding-top: 10px } .sideMenu ul .active, .sideMenu li .active { border-left: 3px solid #d19b3d; background-color: #4f5b69; } .sideMenu ul .sub-menu li.active, .sideMenu li .sub-menu li.active { color: #d19b3d; } .sideMenu ul .sub-menu li, .sideMenu li .sub-menu li { background-color: #181c20; border: none; line-height: 28px; border-bottom: 1px solid #23282e; margin-left: 0px; } .sideMenu ul .sub-menu li:hover, .sideMenu li .sub-menu li:hover { background-color: #020203; } .sideMenu li { padding-left: 0px; border-left: 3px solid #2e353d; border-bottom: 1px solid #23282e; } .sideMenu li a { text-decoration: none; color: #e1ffff; } .sideMenu li a i { padding-left: 10px; width: 20px; padding-right: 20px; } .sideMenu li:hover { border-left: 3px solid #d19b3d; background-color: #4f5b69; -webkit-transition: all 1s ease; -moz-transition: all 1s ease; -o-transition: all 1s ease; -ms-transition: all 1s ease; transition: all 1s ease; } @media (max-width: 768px) { #navbar { visibility: visible; } .sideMenu { visibility: hidden; } } @media (min-width: 769px) { #navbar { visibility: hidden; } .sideMenu { visibility: visible; } }
JavaScript代码
$(document).ready(function () { $('.collapsed').on('click dblclick', function (ev) { if ($('.active').length > 0 && !$(this).hasClass("active")) { $('.active').trigger("click"); $('.active').removeClass("active"); } $(this).addClass("active"); }); $('.sub-menu li').on('click dblclick', function (ev) { ev.stopPropagation(); }) });
问题原因
快速点击会触发多次click和dblclick事件,事件队列堆积导致原代码中$('.active').trigger("click")的执行时机混乱;同时Bootstrap的collapse动画尚未完成时,菜单的active类和折叠状态就被修改,最终造成多个菜单同时处于展开状态。
修复方案
修复思路
- 移除
dblclick事件监听,避免重复触发事件 - 手动控制菜单状态:点击当前菜单前,先关闭所有其他已展开的菜单
- 阻止Bootstrap默认折叠事件,避免自定义逻辑与框架默认逻辑冲突
修复后的JavaScript代码
$(document).ready(function () { $('.collapsed').on('click', function (ev) { ev.preventDefault(); ev.stopPropagation(); const $current = $(this); const targetId = $current.data('target'); // 关闭所有其他展开的菜单 $('.collapsed').not($current).each(function() { const $other = $(this); const otherTarget = $other.data('target'); if (!$(otherTarget).hasClass('collapse')) { $(otherTarget).collapse('hide'); $other.addClass('collapsed').removeClass('active'); } }); // 切换当前菜单的展开/折叠状态 $(targetId).collapse('toggle'); $current.toggleClass('active collapsed'); }); $('.sub-menu li').on('click', function (ev) { ev.stopPropagation(); }); });
效果说明
修复后,无论如何快速点击菜单,同一时间只会有一个菜单处于展开状态,彻底解决了多菜单同时展开的异常问题。
内容的提问来源于stack exchange,提问作者Mohamed
相关产品推荐
相关产品推荐

