首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >本机引导程序不适用于Turbo链路

本机引导程序不适用于Turbo链路
EN

Stack Overflow用户
提问于 2017-10-20 21:01:35
回答 4查看 1.9K关注 0票数 3

我正试图让自举原生在Rails 5应用程序中与Turbolinks 5一起工作。当我第一次加载页面时,Bootstrap下拉菜单工作正常,但是在导航到另一个页面之后,Bootstrap下拉菜单就不再工作了。就好像Bootstrap的事件侦听器被断开了一样。

我看到了几个问题,涉及到Bootstrap的jQuery实现,但是,我对使用自举原生和从JS堆栈中消除jQuery很感兴趣。

以下是一些细节:

application.js

代码语言:javascript
复制
# app/assets/javascript/application.js
//= require turbolinks
//= require rails-ujs
//= require polyfill
//= require bootstrap-native

应用程序布局

代码语言:javascript
复制
# 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抛出异常。

对如何解决这个问题有什么想法吗?

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2017-10-31 10:55:04

这里的BSN开发人员,为什么不在BSN库之外添加这个自定义代码,以便更容易地维护呢?

代码语言:javascript
复制
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

代码语言:javascript
复制
var container = document.getElementById('myContainer');
document.addEventListener('turbolinks:load', function(){
  container = container || document.getElementById('myContainer');
  BSN.initCallback(container);
}, false);

如果在控制台中键入BSN点击Enter,将得到以下对象:

代码语言:javascript
复制
BSN = {
  version: '2.0.20',
  initCallback: function(lookup){},
  supports: [ /* an array with supported components */ ]
}

请记住,您不必使用myContainer作为您的turbolinks目标的ID属性,您可以使用任何东西来使该元素惟一,我建议使用像data-function="turbolinks-autoload"这样的选择器。

下载最新的主人并试一试。

票数 3
EN

Stack Overflow用户

发布于 2017-10-21 09:41:19

在使用Turbolinks时,您很可能希望将应用程序JavaScript文件放在<head>

代码语言:javascript
复制
# 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上)删除。

票数 1
EN

Stack Overflow用户

发布于 2017-10-21 18:59:30

主要修订版

在Bootstrap本地开发团队的一位成员接受了这个答案之后,我已经修改了我在我的应用程序中实现的解决方案。我的解决方案与接受的解决方案略有不同,因为我的侦听器将在整个DOM中搜索引导组件。相比之下,接受的解决方案将只在具有id="myContainer的HTML标记中进行搜索。接受的解决方案将执行得更快,因为它只搜索DOM的一个子集。但是,它要求开发人员将相关的引导组件封装在带有myContainer id的标记中。

这两种解决方案都有效。我的解决方案将运行得稍微慢一点,但会导致更容易编写代码,并且不太容易出现开发人员引发的bug。以下是详细信息:

app/assets/javascript/application.js

代码语言:javascript
复制
//= require turbolinks
//= require rails-ujs
//= require polyfill
//= require bootstrap-native
//= require bootstrap-native-turbolinks

app/assets/javascript/bootstrap-native-turbolinks.js

代码语言:javascript
复制
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

代码语言:javascript
复制
...
<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。自举原生可以显著提高应用程序的下载时间。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/46857297

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档