本文详解如何修改 Bootstrap 4.5 默认行为,使 navbar 中多个 .dropdown 可独立开关、互不关闭,适用于侧边栏(sidemenu)等需多级展开的场景。核心是拦截 hide.bs.dropdown 事件并智能判断关闭动因。
本文详解如何修改 bootstrap 4.5 默认行为,使 navbar 中多个 `.dropdown` 可独立开关、互不关闭,适用于侧边栏(sidemenu)等需多级展开的场景。核心是拦截 `hide.bs.dropdown` 事件并智能判断关闭动因。
Bootstrap 4.5 的下拉菜单(Dropdown)默认采用“单例模式”:当一个下拉菜单打开时,其他已展开的菜单会自动收起。这一设计在顶部导航栏中合理,但在作为侧边菜单(sidemenu)使用时,用户往往需要同时展开多个分类(如“Contracts”和“Quote & Order”)进行跨组操作。原生 Bootstrap 并未提供 multiple: true 这类配置项,因此需通过事件干预实现多开支持。
✅ 正确解决方案:事件驱动的智能防关闭
关键思路是区分两种关闭行为:
- 显式关闭:用户点击已展开菜单的 toggle 按钮(即再次点击同一触发器)→ 允许关闭;
- 隐式关闭:用户点击其他菜单的 toggle 按钮 → 阻止当前菜单被意外关闭。
Bootstrap 提供了 show.bs.dropdown 和 hide.bs.dropdown 事件,但注意:hide.bs.dropdown 在「因新菜单打开而触发旧菜单关闭」时先于目标菜单的 show.bs.dropdown 触发,且其 e.relatedTarget 指向新触发的 toggle 元素(而非 null)。这正是我们做判断的依据。
以下是精简、健壮的实现代码:
// 存储最后一次点击的下拉触发器(nav-link.dropdown-toggle)
let lastTrigger = null;
// 记录每次点击的触发器元素
$('.nav-link.dropdown-toggle').on('click', function() {
lastTrigger = this;
});
// 监听所有下拉容器的隐藏事件
$('.dropdown').on('hide.bs.dropdown', function(e) {
// 若存在 lastTrigger,且它 ≠ 当前 hide 事件的 relatedTarget,
// 说明本次隐藏是由「点击其他下拉按钮」引发的 —— 阻止默认关闭行为
if (lastTrigger && lastTrigger !== e.relatedTarget) {
e.preventDefault();
}
});
⚠️ 注意事项:
- 该逻辑必须在 Bootstrap JS 初始化之后执行(确保 data-toggle="dropdown" 已绑定);
- 不要移除或覆盖 Bootstrap 原生的 data-toggle 属性,否则下拉功能将完全失效;
- 避免对 .dropdown-item 单独加 e.stopPropagation()(如原始代码所示),这会破坏下拉菜单内链接跳转及 checkbox 交互;
- 若需支持键盘操作(如 Esc 关闭),此方案仍兼容,因为 Esc 触发的 hide 事件中 e.relatedTarget 为 null,不会被阻止。
? 补充:适配你的侧边栏结构
你已将 navbar 改造成固定高度侧边菜单,并添加了自定义滚动与动画。上述 JS 逻辑可无缝集成——只需确保它在 bootstrap.bundle.min.js 加载后执行即可。推荐将其置于文档末尾或 $(document).ready() 中:
$(function() {
// 侧边栏高度适配(保留原有逻辑)
const fixHeight = () => {
$('.navbar-nav').css('max-height', $(window).height() - 150);
};
fixHeight();
$(window).resize(fixHeight);
// 多下拉菜单支持(核心逻辑)
let lastTrigger = null;
$('.nav-link.dropdown-toggle').on('click', function() {
lastTrigger = this;
});
$('.dropdown').on('hide.bs.dropdown', function(e) {
if (lastTrigger && lastTrigger !== e.relatedTarget) {
e.preventDefault();
}
});
// 移动端菜单开关(保留原有逻辑)
$('.navbar-toggler, .overlay').on('click', function() {
$('.mobileMenu, .overlay').toggleClass('open');
});
});
✅ 效果验证
启用后,你可以:
- 点击「Contracts」→ 下拉展开;
- 再点击「Quote & Order」→ 两个菜单同时保持展开状态;
- 再次点击任一已展开菜单的 toggle 按钮 → 仅该菜单收起,另一个保持开启;
- 点击空白处或按 Esc 键 → 所有展开菜单统一收起(符合预期交互)。
此方案轻量、无侵入、兼容 Bootstrap 官方生命周期,是解决 Bootstrap 4.x 多下拉共存问题的推荐实践。










