You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Rails7+Bootstrap5汉堡菜单可展开但无法收起问题

Rails 7 + Bootstrap 5汉堡菜单可展开但无法收起的问题排查与解决

问题概述

使用Ruby on Rails 7搭配Bootstrap 5开发时,汉堡菜单点击可正常展开,但再次点击无法收起;其他Bootstrap下拉组件功能均正常。替换Bootstrap官方导航示例代码后问题依旧,可排除导航视图代码本身的问题。

排查过程

通过注释不同JS资源组合测试发现:

  • 仅当同时注释以下两项时,汉堡菜单恢复正常功能:
    1. 旧版本Bootstrap JS引入(5.3.0-alpha1的bundle.js)
    2. Rails的javascript_include_tag "application"
  • 单独注释其中任意一项,问题仍存在。

相关代码细节

导航视图代码

<nav class="navbar navbar-expand-lg bg-dark border-bottom border-body" data-bs-theme="dark">
  <div class="container-fluid">
    <a class="navbar-brand" href="/" style="color: white">ContactPoints.io</a>
    <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarTogglerDemo02" aria-controls="navbarTogglerDemo02" aria-expanded="false" aria-label="Toggle navigation">
      <span class="navbar-toggler-icon"></span>
    </button>
    <div class="collapse navbar-collapse" id="navbarTogglerDemo02">
      <ul class="navbar-nav ms-auto mb-2 mb-lg-0">
        <% if current_user %>
          <%= render "layouts/logged_in_nav" %>
        <% else %>
          <%= render "layouts/logged_out_nav" %>
        <% end %>
      </ul>
    </div>
  </div>
</nav>

布局文件中的JS/CSS引入

<!DOCTYPE html>
<html>
  <head>
    <title>Contact Points</title>
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <%= csrf_meta_tags %>
    <%= csp_meta_tag %>
    <%= favicon_link_tag 'favicon.ico' %>

    <%= stylesheet_link_tag "application", "data-turbo-track": "reload" %>
    <%= javascript_include_tag "application", "data-turbo-track": "reload", defer: true %>

    <%# Bootstrap 5 JS %>
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz" crossorigin="anonymous"></script>

    <%# Bootstrap 5 CSS %>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">

    <!-- Include Stripe javascript -->
    <script src="https://js.stripe.com/v3"></script>

    <!-- Include Bootstrap modal library -->
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/js/bootstrap.bundle.min.js"></script>

    <script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>

    <script src="https://cdn.jsdelivr.net/gh/xcash/bootstrap-autocomplete@v2.3.7/dist/latest/bootstrap-autocomplete.min.js"></script>
  </head>
  <body>
    <%= render '/layouts/topnav' %>
    <% if flash[:alert].present? %>
      <div style="background-color: yellow; text-align: center; padding: 10px;">
        <%= flash[:alert] %>
      </div>
    <% end %>
    <br>
    <%= yield %>
  </body>
</html>

两个application.js代码

javascript/controllers/application.js

import { Application } from "@hotwired/stimulus"
// import "controllers"

const application = Application.start()

// Configure Stimulus development experience
application.debug = false
window.Stimulus   = application

export { application }

console.log("other javascript.js is being called");
console.log("why do we have two application.js?");

//= require pagy
//= require pagy/extras/bootstrap

主javascript/application.js

// Entry point for the build script in your package.json
import "@hotwired/turbo-rails"
import "./controllers"
import * as bootstrap from "bootstrap"

console.log("application js is being called")

问题根源分析

  1. 多重Bootstrap JS版本冲突:
    • 同时引入了Bootstrap 5.3.3稳定版和5.3.0-alpha1旧版本的bundle.js,加上主application.js中import * as bootstrap from "bootstrap"的npm版本,导致Bootstrap的Collapse组件初始化多次,事件绑定异常。
  2. Rails JS加载方式冲突:
    • Rails 7默认使用jsbundling(如esbuild),javascript_include_tag用于传统asset pipeline,与jsbundling的加载方式可能存在重复加载或初始化顺序问题,加剧了组件冲突。
  3. 冗余jQuery引入:
    • Bootstrap 5已不再依赖jQuery,引入jQuery slim可能导致潜在的DOM事件冲突。

解决方案

1. 清理重复的Bootstrap JS引入

  • 移除布局中旧版本的Bootstrap JS:<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/js/bootstrap.bundle.min.js"></script>
  • 统一Bootstrap引入方式:
    • 选择CDN方式:保留5.3.3的bundle.js,移除主application.js中的import * as bootstrap from "bootstrap"
    • 选择npm方式:移除CDN的Bootstrap JS引入,保留import * as bootstrap from "bootstrap",确保npm安装的Bootstrap版本为5.3.3

2. 修正Rails JS加载方式

  • 若使用jsbundling(默认),将布局中的javascript_include_tag替换为javascript_importmap_tags(如果用importmap)或javascript_pack_tag(如果用webpacker),确保JS资源加载正确,避免重复加载。

3. 处理Turbo的事件绑定问题

  • 由于Turbo会动态更新DOM,可手动在Turbo加载完成后初始化Collapse组件,添加到主application.js:
    document.addEventListener('turbo:load', () => {
      const navbarCollapse = document.getElementById('navbarTogglerDemo02');
      if (navbarCollapse) {
        new bootstrap.Collapse(navbarCollapse, { toggle: false });
      }
    });
    

4. 移除冗余jQuery

  • 删除布局中的jQuery slim引入,避免不必要的冲突。

总结

核心问题是多重Bootstrap版本冲突加上Rails JS加载方式的重复/冲突,导致汉堡菜单的Collapse组件事件绑定异常。通过清理重复资源、统一引入方式、适配Turbo的DOM更新机制,即可解决菜单无法收起的问题。

内容的提问来源于stack exchange,提问作者Monroe Mann

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 06:34:54