Bootstrap 移动端菜单点击后无法关闭,根本原因是重复加载了 Bootstrap JavaScript(尤其是 bootstrap.min.js 与 bootstrap.bundle.min.js 同时存在),导致事件监听器冲突和组件初始化异常。
bootstrap 移动端菜单点击后无法关闭,根本原因是重复加载了 bootstrap javascript(尤其是 `bootstrap.min.js` 与 `bootstrap.bundle.min.js` 同时存在),导致事件监听器冲突和组件初始化异常。
在使用外部 HTML 文件(如 header.html)动态注入导航栏时,开发者常误以为问题出在「分离式结构」上——例如通过 fetch() 加载 <nav> 内容。但实际与文件拆分无关,核心症结在于 Bootstrap 的重复引入。
Bootstrap 提供两种 JS 包:
- bootstrap.bundle.min.js:已内置 Popper(用于下拉、tooltip 等定位),无需额外引入;
- bootstrap.min.js:需单独搭配 Popper 和 jQuery(旧版) 才能正常工作。
你的原始代码中同时加载了:
<!-- ✅ 正确:bundle 版本(含 Popper) --> <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script> <!-- ❌ 冲突:额外加载独立 Popper + bootstrap.min.js --> <script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.11.8/dist/umd/popper.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.min.js"></script>
这种双重加载会导致:
- Navbar 组件被初始化两次;
- data-bs-toggle="collapse" 的点击事件绑定混乱;
- aria-expanded 属性状态与 DOM 实际折叠状态不同步 → 菜单“看似打开”,实则控制逻辑失效。
✅ 正确做法:仅保留 bootstrap.bundle.min.js,彻底移除后续所有 Popper 和 bootstrap.min.js 的 <script> 标签。
✅ 修复后的 index.html 关键片段
<head>
<!-- Bootstrap CSS -->
<link
href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css"
rel="stylesheet"
integrity="sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN"
crossorigin="anonymous">
<!-- ✅ 唯一 JS:bootstrap.bundle.min.js(含 Popper) -->
<script
src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"
integrity="sha384-C6RzsynM9kWDrMNeT87bh95OGNyZPhcTNXj1NW7RuBCsyN/o0jlpcV8Qyq46cDfL"
crossorigin="anonymous"></script>
<!-- Bootstrap Icons(可选) -->
<link
rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.css">
</head>
<body>
<header>
<script>
document.addEventListener("DOMContentLoaded", function () {
fetch('header.html')
.then(response => response.text())
.then(data => {
document.querySelector('header').innerHTML = data;
})
.catch(err => console.error("Header load failed:", err));
});
</script>
</header>
<!-- ⚠️ 此处不再添加任何 Popper 或 bootstrap.min.js -->
</body>? 验证技巧
- 打开浏览器开发者工具(F12)→ Console,输入 bootstrap 或 bootstrap.Alert,若报错或返回 undefined,说明 Bootstrap 未正确加载;
- 检查 Elements 面板中 <button> 的 aria-expanded 属性:点击后应切换为 "true"/"false";若始终为 "false" 或不变化,即为初始化失败。
? 补充建议
- 动态注入 HTML 后,Bootstrap 组件(如 Collapse、Dropdown)会自动初始化,无需手动调用 new bootstrap.Collapse(...) —— 这是 Bootstrap 5+ 的默认行为;
- 若未来需在 fetch 完成后执行自定义逻辑(如监听 collapse 事件),可使用原生事件:
document.addEventListener('show.bs.collapse', (e) => { console.log('Menu opening:', e.target.id); });
遵循「一次加载、完整 bundle」原则,即可彻底解决移动端菜单卡死问题,且兼容 header 分离、SPA 式结构等现代前端实践。


















