
本文详解如何在 Bootstrap 4.5 中实现多个导航栏下拉菜单同时保持展开状态,通过拦截 hide.bs.dropdown 事件并结合点击溯源逻辑,避免默认的“一开一关”互斥行为。
本文详解如何在 bootstrap 4.5 中实现多个导航栏下拉菜单同时保持展开状态,通过拦截 `hide.bs.dropdown` 事件并结合点击溯源逻辑,避免默认的“一开一关”互斥行为。
在 Bootstrap 4.5 默认行为中,当一个 .dropdown 被打开时,其他已展开的下拉菜单会自动收起——这是由其内部的 Dropdown 插件强制实现的互斥逻辑所致。但在侧边栏(sidemenu)等自定义场景中,用户常需多级菜单并行展开,例如同时查看“Contracts”和“Quote & Order”子项,此时默认行为反而成为障碍。
解决该问题的关键不在于阻止所有关闭操作,而在于区分关闭意图:
✅ 允许用户主动点击同一 toggle 按钮来关闭当前下拉菜单;
❌ 阻止因点击其他 dropdown-toggle 导致的“连带关闭”。
Bootstrap 提供了标准事件钩子 show.bs.dropdown 和 hide.bs.dropdown,但直接监听 hide.bs.dropdown 并 e.preventDefault() 会导致所有关闭失效(包括手动关闭),因此必须精准判断触发原因。
✅ 推荐方案:基于 relatedTarget 的智能拦截
Bootstrap 在 hide.bs.dropdown 事件中会将触发新展开的元素(即用户刚点击的另一个 .dropdown-toggle)赋值给 e.relatedTarget。我们可利用这一机制,配合记录最近一次点击的 toggle 元素,实现条件拦截:
let lastTrigger = null;
// 记录每次点击的 dropdown-toggle 元素
$('.nav-link.dropdown-toggle').on('click', function() {
lastTrigger = this;
});
// 在 hide 事件中判断:若关闭非因点击自身触发,则阻止默认关闭
$('.dropdown').on('hide.bs.dropdown', function(e) {
if (lastTrigger && lastTrigger !== e.relatedTarget) {
e.preventDefault();
}
});? 原理说明:当用户点击「Contracts」toggle 时,lastTrigger 指向它;随后点击「Quote & Order」toggle,Bootstrap 触发「Contracts」的 hide.bs.dropdown 事件,此时 e.relatedTarget 指向「Quote & Order」toggle —— 二者不等,故 e.preventDefault() 生效,Contracts 下拉菜单保持展开。
⚠️ 注意事项与最佳实践
- ID 唯一性:示例中两个 <a> 均使用 id="navbarDropdown",这违反 HTML 规范(ID 必须唯一),虽不影响功能,但建议改为类名(如 class="dropdown-toggle-btn")或动态 ID(如 id="dropdown-contracts"),避免潜在冲突。
-
事件委托兼容性:若菜单为动态渲染(如 AJAX 加载),请改用事件委托:
$(document).on('click', '.nav-link.dropdown-toggle', function() { lastTrigger = this; }); $(document).on('hide.bs.dropdown', '.dropdown', function(e) { if (lastTrigger && lastTrigger !== e.relatedTarget) { e.preventDefault(); } }); - 移动端适配:本方案对桌面端和触屏设备均有效;若需支持手势关闭(如点击空白处),可额外监听 document 点击事件并重置 lastTrigger,但通常非必需。
- Bootstrap 版本注意:代码基于 Bootstrap 4.5+(对应文档 v4.6),不适用于 Bootstrap 5(其事件命名及 API 已变更,需使用 bs.dropdown 命名空间及 hidePrevented 判断)。
✅ 完整初始化脚本(含侧边栏适配)
将以下 JS 放置于 Bootstrap Bundle 之后、自定义逻辑之前即可生效:
<script>
$(function() {
// 侧边栏高度适配(保留原有逻辑)
const fixHeight = () => {
$('.navbar-nav').css('max-height', document.documentElement.clientHeight - 150);
};
fixHeight();
$(window).resize(fixHeight);
$('.navbar .navbar-toggler').on('click', fixHeight);
// 移动端菜单开关
$('.navbar-toggler, .overlay').on('click', function() {
$('.mobileMenu, .overlay').toggleClass('open');
});
// ✨ 核心:允许多个下拉菜单并行展开
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();
}
});
});
</script>至此,你的 Bootstrap 4.5 侧边栏导航即可支持任意数量下拉菜单独立开关、并行展开,兼顾用户体验与代码健壮性。无需修改 Bootstrap 源码,纯前端事件控制,轻量且可维护性强。

















