我正试图让自举原生在Rails 5应用程序中与Turbolinks 5一起工作。当我第一次加载页面时,Bootstrap下拉菜单工作正常,但是在导航到另一个页面之后,Bootstrap下拉菜单就不再工作了。就好像Bootstrap的事件侦听器被断开了一样。
我看到了几个问题,涉及到Bootstrap的jQuery实现,但是,我对使用自举原生和从JS堆栈中消除jQuery很感兴趣。
以下是一些细节:
application.js
# app/assets/javascript/application.js
//= require turbolinks
//= require rails-ujs
//= require polyfill
//= require bootstrap-native应用程序布局
# 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>bootstrap-native,这是引导本机包。
从Javascript标记中删除'data-turbolinks-eval': 'false',从而重新评估应用程序在每个Turbolink导航上的所有Javascript,确实解决了引导本机问题,但它会导致rails-ujs抛出异常。
对如何解决这个问题有什么想法吗?
发布于 2017-10-31 10:55:04
这里的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更新,因为您不更新任何其他内容,并且需要尽可能快地更新。
我还更新了wiki页面,以包括一个通用示例。
UPDATE从BSNVersion2.0.20开始,您可以在站点<head>中使用库而不需要任何额外的脚本,您可以更容易地完成这个turbolinks:
var container = document.getElementById('myContainer');
document.addEventListener('turbolinks:load', function(){
container = container || document.getElementById('myContainer');
BSN.initCallback(container);
}, false);如果在控制台中键入BSN点击Enter,将得到以下对象:
BSN = {
version: '2.0.20',
initCallback: function(lookup){},
supports: [ /* an array with supported components */ ]
}请记住,您不必使用myContainer作为您的turbolinks目标的ID属性,您可以使用任何东西来使该元素惟一,我建议使用像data-function="turbolinks-autoload"这样的选择器。
下载最新的主人并试一试。
发布于 2017-10-21 09:41:19
在使用Turbolinks时,您很可能希望将应用程序JavaScript文件放在<head>中
# 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' %>
<%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %>
</head>
<body>
<%= render 'layouts/header' %>
<div class="container">
<%= yield %>
</div>
</body>
</html>尽管这似乎违背了传统的最佳实践,但Turbolinks的性能优势在于脚本只在初始页面加载时加载。
如果引导本机库在DOMContentLoaded上初始化其插件/函数,您可能还需要在turbolinks:load上手动调用这些函数,然后在必要时将它们(通常在turbolinks:before-cache上)删除。
发布于 2017-10-21 18:59:30
主要修订版
在Bootstrap本地开发团队的一位成员接受了这个答案之后,我已经修改了我在我的应用程序中实现的解决方案。我的解决方案与接受的解决方案略有不同,因为我的侦听器将在整个DOM中搜索引导组件。相比之下,接受的解决方案将只在具有id="myContainer的HTML标记中进行搜索。接受的解决方案将执行得更快,因为它只搜索DOM的一个子集。但是,它要求开发人员将相关的引导组件封装在带有myContainer id的标记中。
这两种解决方案都有效。我的解决方案将运行得稍微慢一点,但会导致更容易编写代码,并且不太容易出现开发人员引发的bug。以下是详细信息:
app/assets/javascript/application.js
//= require turbolinks
//= require rails-ujs
//= require polyfill
//= require bootstrap-native
//= require bootstrap-native-turbolinksapp/assets/javascript/bootstrap-native-turbolinks.js
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);vendor/assets/javascripts/
最后,我将我的应用程序javascript标记移动到<head>中,并在不使用tuborlinks eval和turbolinks-跟踪的情况下异步加载它。这将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都小于20 is。相比之下,jQuery本身就缩小了86 By。自举原生可以显著提高应用程序的下载时间。
https://stackoverflow.com/questions/46857297
复制相似问题