Rails 6 Webpacker中使用Bootstrap tooltip/popover报$(...).tooltip非函数错误
报错根因梳理
首先澄清两个常见认知误区:
- 你猜测的「jquery-ui已包含在jquery-ujs中」完全不成立:jquery-ujs是Rails用来处理异步请求、CSRF校验的轻量工具,和负责UI交互的jquery-ui是完全独立的两个库,没有任何包含关系。
- 你遇到的
tooltip is not a function报错和jquery-ui没有任何关系:Bootstrap 4及以上版本自带的tooltip、popover组件,本身不依赖jquery-ui,盲目引入jquery-ui反而会引发样式、事件冲突,这也是你之前引入后破坏现有应用的原因。
现有代码的具体问题
顺着你提供的application.js逻辑逐行排查,一共三个核心问题直接导致了报错:
- 加载顺序完全倒置:你现在的代码流程是先加载Bootstrap,隔了十几行才执行jQuery的全局挂载。Bootstrap初始化时需要找到全局挂载的jQuery对象,才能把tooltip、popover等扩展方法绑定到jQuery的原型上,等你后面才挂载jQuery的时候,Bootstrap早就初始化完了,自然不会给jQuery添加这些方法。
- 全局挂载存在变量名错误:你最后写的jQuery导入逻辑是
import JQuery from 'jquery'; window.jQuery = $; window.$ = $;——这里你导入的变量名是大写的JQuery,但赋值时引用的$在当前模块作用域根本没有定义,相当于你最终挂到全局的jQuery是一个undefined值,Bootstrap根本找不到可用的jQuery实例。 - 重复导入Bootstrap:代码里同时写了
require("bootstrap")和import "bootstrap",虽然不会直接导致报错,但会造成重复初始化的冗余逻辑。
修正方案
按照依赖加载的先后顺序重排application.js内容,修正变量名错误,最终结构参考如下:
// 1. 优先加载Rails基础能力 require("@rails/ujs").start() require("turbolinks").start() require("@rails/activestorage").start() require("channels") // 2. 第二步加载并全局挂载jQuery,必须放在所有依赖jQuery的库之前 import $ from 'jquery' window.$ = $ window.jQuery = $ // 3. 加载其他无依赖的基础工具库 require("js.cookie") require("react") require("react-dom") require.context('../images', true) // 4. 第三步加载Bootstrap,此时能正常识别全局的$,完成组件方法的挂载 import 'bootstrap' // 5. 加载其他业务依赖库与样式 import "blueimp-gallery" import "../stylesheets/application" // 6. 最后放置Turbolinks页面切换的初始化逻辑 document.addEventListener("turbolinks:load", () => { $('[data-toggle="tooltip"]').tooltip() $('[data-toggle="popover"]').popover() })
补充排查注意点
- 确认项目的Bootstrap版本:如果是Bootstrap 5,它已经完全移除了对jQuery的依赖,此时用
$().tooltip()的写法必然报错,需要替换为Bootstrap 5要求的原生JS初始化逻辑;根据你现有代码的调用方式,大概率是Bootstrap 4版本,上述修正逻辑可直接生效。 - 删掉重复的样式导入行:你代码中两次引入了
../stylesheets/application,删除冗余的那行即可,不影响功能但能减小打包体积。 - 完全不需要引入jquery-ui:当前的报错逻辑和它没有任何关系,引入反而会引发兼容问题。
内容的提问来源于stack exchange,提问作者Mices
相关产品推荐
相关产品推荐

