Javascript 引导程序本机不适用于Turbo链接
我正在尝试在Rails 5应用程序中使用。当我第一次加载页面时,引导下拉菜单工作正常,但导航到另一个页面后,引导下拉菜单不再工作。这就好像引导程序的事件侦听器断开了连接 在Bootstrap的jQuery实现方面,我已经看到了几个解决这个问题的问题,但是,我对使用jQuery并从我的JS堆栈中删除jQuery感兴趣 以下是一些细节: application.jsJavascript 引导程序本机不适用于Turbo链接,javascript,ruby-on-rails,turbolinks,turbolinks-5,bootstrap-native,Javascript,Ruby On Rails,Turbolinks,Turbolinks 5,Bootstrap Native,我正在尝试在Rails 5应用程序中使用。当我第一次加载页面时,引导下拉菜单工作正常,但导航到另一个页面后,引导下拉菜单不再工作。这就好像引导程序的事件侦听器断开了连接 在Bootstrap的jQuery实现方面,我已经看到了几个解决这个问题的问题,但是,我对使用jQuery并从我的JS堆栈中删除jQuery感兴趣 以下是一些细节: application.js # app/assets/javascript/application.js //= require turbolinks //= r
# app/assets/javascript/application.js
//= require turbolinks
//= require rails-ujs
//= require polyfill
//= require bootstrap-native
//= require turbolinks
//= require rails-ujs
//= require polyfill
//= require bootstrap-native
//= require bootstrap-native-turbolinks
document.addEventListener('turbolinks:load', function(){
Array.prototype.forEach.call(document.querySelectorAll('[data-spy="affix"]'), function(element){ new Affix(element) });
Array.prototype.forEach.call(document.querySelectorAll('[data-dismiss="alert"]'), function(element){ new Alert(element) });
Array.prototype.forEach.call(document.querySelectorAll('[data-toggle="buttons"]'), function(element){ new Button(element) });
Array.prototype.forEach.call(document.querySelectorAll('[data-ride="carousel"]'), function(element){ new Carousel(element) });
Array.prototype.forEach.call(document.querySelectorAll('[data-toggle="collapse"]'), function(element){ new Collapse(element) });
Array.prototype.forEach.call(document.querySelectorAll('[data-toggle="dropdown"]'), function(element){ new Dropdown(element) });
Array.prototype.forEach.call(document.querySelectorAll('[data-toggle="modal"]'), function(element){ new Modal(element) });
Array.prototype.forEach.call(document.querySelectorAll('[data-toggle="popover"]'), function(element){ new Popover(element) });
Array.prototype.forEach.call(document.querySelectorAll('[data-spy="scroll"]'), function(element){ new ScrollSpy(element) });
Array.prototype.forEach.call(document.querySelectorAll('[data-toggle="tab"]'), function(element){ new Tab(element) });
Array.prototype.forEach.call(document.querySelectorAll('[data-toggle="tooltip"]'), function(element){ new Tooltip(element) });
},false);
应用程序布局
# views/layout/application.html.erb
<!DOCTYPE html>
<html>
<head>
<title><%= full_title(yield(:title)) %></title>
<%= csrf_meta_tags %>
<%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
</head>
<body>
<%= render 'layouts/header' %>
<div class="container">
<%= yield %>
</div>
<%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload', 'data-turbolinks-eval': 'false' %>
</body>
</html>
#视图/layout/application.html.erb
本机引导程序
这是最新的
从我的Javascript标记中删除“data-turbolinks-eval”:“false”
,从而在每个Turbolink导航上重新评估应用程序的所有Javascript,确实解决了引导本机问题,但它会导致rails ujs引发异常
有没有关于如何解决这个问题的想法?使用TurboLink时,您很可能希望将应用程序JavaScript文件放在
中:
#视图/layout/application.html.erb
尽管这似乎与传统的最佳实践背道而驰,但Turbolinks的性能优势在于脚本只在初始页面加载时加载
如果引导程序本机库在
DOMContentLoaded
上初始化其插件/函数,您可能还需要在turbolinks:load
上手动调用这些函数,然后根据需要将它们拆下(通常在turbolinks:before cache
)
在Bootstrap原生开发团队的一名成员接受了答案之后,我修改了我在应用程序中实现的解决方案。我的解决方案与公认的解决方案略有不同,因为我的侦听器将在整个DOM中搜索引导组件。相比之下,接受的解决方案将只在具有id=“myContainer
的HTML标记中搜索。接受的解决方案将执行得更快,因为它只搜索DOM的子集。但是,它要求开发人员将相关引导组件包装在具有myContainer
id的标记中
这两种解决方案都有效。我的解决方案运行速度会稍微慢一点,但会更容易编码,并且不太容易出现由开发人员引起的错误。以下是详细信息:
app/assets/javascript/application.js
# app/assets/javascript/application.js
//= require turbolinks
//= require rails-ujs
//= require polyfill
//= require bootstrap-native
//= require turbolinks
//= require rails-ujs
//= require polyfill
//= require bootstrap-native
//= require bootstrap-native-turbolinks
document.addEventListener('turbolinks:load', function(){
Array.prototype.forEach.call(document.querySelectorAll('[data-spy="affix"]'), function(element){ new Affix(element) });
Array.prototype.forEach.call(document.querySelectorAll('[data-dismiss="alert"]'), function(element){ new Alert(element) });
Array.prototype.forEach.call(document.querySelectorAll('[data-toggle="buttons"]'), function(element){ new Button(element) });
Array.prototype.forEach.call(document.querySelectorAll('[data-ride="carousel"]'), function(element){ new Carousel(element) });
Array.prototype.forEach.call(document.querySelectorAll('[data-toggle="collapse"]'), function(element){ new Collapse(element) });
Array.prototype.forEach.call(document.querySelectorAll('[data-toggle="dropdown"]'), function(element){ new Dropdown(element) });
Array.prototype.forEach.call(document.querySelectorAll('[data-toggle="modal"]'), function(element){ new Modal(element) });
Array.prototype.forEach.call(document.querySelectorAll('[data-toggle="popover"]'), function(element){ new Popover(element) });
Array.prototype.forEach.call(document.querySelectorAll('[data-spy="scroll"]'), function(element){ new ScrollSpy(element) });
Array.prototype.forEach.call(document.querySelectorAll('[data-toggle="tab"]'), function(element){ new Tab(element) });
Array.prototype.forEach.call(document.querySelectorAll('[data-toggle="tooltip"]'), function(element){ new Tooltip(element) });
},false);
app/assets/javascript/bootstrap native turbolinks.js
# app/assets/javascript/application.js
//= require turbolinks
//= require rails-ujs
//= require polyfill
//= require bootstrap-native
//= require turbolinks
//= require rails-ujs
//= require polyfill
//= require bootstrap-native
//= require bootstrap-native-turbolinks
document.addEventListener('turbolinks:load', function(){
Array.prototype.forEach.call(document.querySelectorAll('[data-spy="affix"]'), function(element){ new Affix(element) });
Array.prototype.forEach.call(document.querySelectorAll('[data-dismiss="alert"]'), function(element){ new Alert(element) });
Array.prototype.forEach.call(document.querySelectorAll('[data-toggle="buttons"]'), function(element){ new Button(element) });
Array.prototype.forEach.call(document.querySelectorAll('[data-ride="carousel"]'), function(element){ new Carousel(element) });
Array.prototype.forEach.call(document.querySelectorAll('[data-toggle="collapse"]'), function(element){ new Collapse(element) });
Array.prototype.forEach.call(document.querySelectorAll('[data-toggle="dropdown"]'), function(element){ new Dropdown(element) });
Array.prototype.forEach.call(document.querySelectorAll('[data-toggle="modal"]'), function(element){ new Modal(element) });
Array.prototype.forEach.call(document.querySelectorAll('[data-toggle="popover"]'), function(element){ new Popover(element) });
Array.prototype.forEach.call(document.querySelectorAll('[data-spy="scroll"]'), function(element){ new ScrollSpy(element) });
Array.prototype.forEach.call(document.querySelectorAll('[data-toggle="tab"]'), function(element){ new Tab(element) });
Array.prototype.forEach.call(document.querySelectorAll('[data-toggle="tooltip"]'), function(element){ new Tooltip(element) });
},false);
供应商/资产/javascripts/
- 从
- 从
并在不使用tuborlinks eval和turbolinks track的情况下异步加载它。这将javascript配置为在初始页面加载时运行一次。每次访问turbolinks页面时都会调用turbolinks:load
侦听器,并附加引导本机事件列表在DOM中的适当组件中调用
app/views/layouts/application.html.erb
...
<head>
...
<%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload', 'data-turbolinks-eval': 'false', async: true %>
</head>
...
。。。
...
...
在撰写本文时,此解决方案已在Rails 5.1应用程序的生产环境中
顺便说一句,application.js中列出的所有Javascript在连接和缩小时都小于20KB。相比之下,它本身就缩小了86KB。可以显著缩短应用程序的下载时间。BSN开发者在这里想,为什么不在BSN库之外添加此自定义代码,以便于维护
var container = document.getElementById('myContainer');
document.addEventListener('turbolinks:load', function(){
container = container || document.getElementById('myContainer');
Array.prototype.forEach.call(container.querySelectorAll('[data-spy="affix"]'), function(element){ new Affix(element) });
Array.prototype.forEach.call(container.querySelectorAll('[data-dismiss="alert"]'), function(element){ new Alert(element) });
Array.prototype.forEach.call(container.querySelectorAll('[data-toggle="buttons"]'), function(element){ new Button(element) });
Array.prototype.forEach.call(container.querySelectorAll('[data-ride="carousel"]'), function(element){ new Carousel(element) });
Array.prototype.forEach.call(container.querySelectorAll('[data-toggle="collapse"]'), function(element){ new Collapse(element) });
Array.prototype.forEach.call(container.querySelectorAll('[data-toggle="dropdown"]'), function(element){ new Dropdown(element) });
Array.prototype.forEach.call(container.querySelectorAll('[data-toggle="modal"]'), function(element){ new Modal(element) });
Array.prototype.forEach.call(container.querySelectorAll('[data-toggle="popover"]'), function(element){ new Popover(element) });
Array.prototype.forEach.call(container.querySelectorAll('[data-spy="scroll"]'), function(element){ new ScrollSpy(element) });
Array.prototype.forEach.call(container.querySelectorAll('[data-toggle="tab"]'), function(element){ new Tab(element) });
Array.prototype.forEach.call(container.querySelectorAll('[data-toggle="tooltip"]'), function(element){ new Tooltip(element) });
},false);
您应该只查看特定的容器turbolinks更新,因为您不更新任何其他内容,您需要尽快更新
我还更新了,添加了一个通用示例
更新
从BSN 2.0.20版开始,您可以使用站点中的库
,而无需任何其他脚本,并且您可以更轻松地执行此TurboLink
:
var container = document.getElementById('myContainer');
document.addEventListener('turbolinks:load', function(){
container = container || document.getElementById('myContainer');
BSN.initCallback(container);
}, false);
如果在控制台中键入BSN
点击回车键,则会得到以下对象:
BSN = {
version: '2.0.20',
initCallback: function(lookup){},
supports: [ /* an array with supported components */ ]
}
请记住,您不必使用myContainer
作为turbolinks目标的ID属性,您可以使用任何东西使该元素唯一,我建议使用类似data function=“turbolinks autoload”
的选择器
下载最新的master并试一试。谢谢。Bootstrap Native使用加载设置。我将尝试添加您推荐的侦听器。我将尝试此解决方案。我过去遇到的一个问题是,TurboLink通过AJAX加载
标记之间的所有内容,然后事件侦听器不会被清除。因此,事件l监听器会不断堆积在这些组件上。也许有办法清除监听器。现代浏览器会立即清除垃圾,但如果你真的想支持带有多填充之类的旧浏览器,你需要分叉/构建你自己的BSN版本,以利用一些destroy()
公共方法。此更新破坏了我的代码。它在第3行抛出了一个未捕获的TypeError:Cannot read属性'querySelectorAll'为null
。将我的整个页面包装在
标记中消除了错误,但仍然禁用了下拉列表。在侦听器中移动var容器…
解决了问题。但是,在nce turbolinks会重新加载
标记之间的所有内容。无论如何,我认为这不会加快速度。我更喜欢你之前的答案。我建议你回过头来。我不同意这一点。对于你的具体情况和所有类似情况,查看单个特定容器而不是整个文档要好得多,在任何情况下,一周中的任何一天,我都会更新我的代码让你重新开始工作。
var bsn = require('bootstrap.native/dist/bootstrap-native-v4');
document.addEventListener('turbolinks:load', () => {
BSN.initCallback();
});