Sar*_*wan 8 ruby-on-rails asset-pipeline turbolinks
我已修改application.html.erb为使用控制器特定资产:
application.html.erb:
<!DOCTYPE html>
<html>
<head>
<title>My Application</title>
<%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track' => true %>
<%= stylesheet_link_tag params[:controller], 'data-turbolinks-track' => true %>
<%= javascript_include_tag 'application', 'data-turbolinks-track' => true %>
<%= javascript_include_tag params[:controller], 'data-turbolinks-track' => true %>
<%= csrf_meta_tags %>
</head>
<body>
... other html template ...
Run Code Online (Sandbox Code Playgroud)
问题是,我安装了turbolinks.当我在同一个控制器中导航时,turbolinks可以工作.但当我切换到另一个控制器时,turbolinks将执行完全重新加载.有没有什么办法解决这一问题?
Ric*_*eck 13
Turbolinks
Turbolinks使用<body>您的HTML页面,并使用Ajax更改它,使该<head>区域保持不变.
这只有在您的<head>意志保持不变的情况下才有效- 否则如何保持不变?因此,在更改控制器页面/资产的意义上,您将不得不在没有Turbolinks的情况下进行整页更新(至少如果您使用Turbolinks而不进行黑客攻击)
我建议修复此问题的方法是更改特定于控制器的资产结构,特别是尽可能少地更改<head>区域.
-
Turbolinks跟踪
阅读后Turbolinks documentation,您可以turbolinks-data-track从控制器特定资产中删除选项中受益:
<%= javascript_include_tag controller_name, 'data-turbolinks-track' => false %>
Run Code Online (Sandbox Code Playgroud)
您可以跟踪某些资产,例如application.js和application.css,您希望确保这些资产始终是Turbolinks会话中的最新版本.这是通过使用data-turbolinks-track标记这些资产链接来完成的,如下所示:
<link href="/assets/application-9bd64a86adb3cd9ab3b16e9dca67a33a.css" rel="stylesheet" type="text/css" data-turbolinks-track>如果这些资产更改了URL(嵌入了md5标记以确保这一点),则该页面将执行完全重新加载而不是通过Turbolinks.这可确保所有Turbolinks会话始终使用最新的JavaScript和CSS.
-
您将从中受益的是使用controller_name帮助程序(代替params[:controller]):
<%= javascript_include_tag 'application', controller_name, 'data-turbolinks-track' => true %>
Run Code Online (Sandbox Code Playgroud)
将您的控制器特定 js 放在 body 标签中。由于 turbolinks 不会触及 html 正文,因此您每次访问该页面时都会重新加载那段 js 代码。
在你的情况下
<body>
<%= javascript_include_tag params[:controller] %>
...
</body>
Run Code Online (Sandbox Code Playgroud)
但是如果你的控制器js中有很多代码,你可能会注意到上面的解决方案有点耗时。因为当您访问该页面时,会重新加载一大块代码。那么如何处理呢?
??以下方法可能会导致一些jquery事件被多次绑定。这是涡轮链接的问题。阅读这篇文章http://staal.io/blog/2013/01/18/dangers-of-turbolinks/
基本上,当用户第一次访问您的网站时,您会加载所有 js 代码,确保不会运行特定于控制器的代码(分别将它们包装在函数中)并将它们保存在一个全局变量中,例如Site. 然后你通过编写类似的东西来触发你的控制器特定的js
<script>
$(document).on("ready page:load", function () {
Site.load('<%= controller_name %>');
}
</script>
Run Code Online (Sandbox Code Playgroud)
在身体标签中。
这样,实际控制器特定的 js 代码只加载一次并在需要时触发。
app/assets/javascripts/site.js
var site;
if(!window.Site) {
site = window.Site = {};
site.controllers = {}
site.load = function (controller) {
if (this.controllers.hasOwnProperty(controller)) {
this.controllers[controller].call();
}
};
site.add = function (controller, fn) {
this.controllers[controller] = fn;
}
}
Run Code Online (Sandbox Code Playgroud)
将您的控制器 js 包装在函数中并将它们保存到Site. 例如,users.js
app/assets/javascripts/site.js
Site.add("users", function () {
// UserController related js code
}
Run Code Online (Sandbox Code Playgroud)
在你的 application.js 中加载它们。
app/assets/javascripts/site.js
//= require jquery
//= require jquery_ujs
//= require turbolinks
//= require site
//= require_tree .
Run Code Online (Sandbox Code Playgroud)
然后在您的布局中触发控制器特定的 js。
app/views/layouts/application.html.erb
<body>
<script>
$(document).on("page:load", function () {
Site.load('<%= controller_name %>');
}
</script>
<%= yield %>
</body>
Run Code Online (Sandbox Code Playgroud)
只需修改site.js和布局。我用以下代码段结束它。
(function (global) {
var site;
if(global.Site) {
return;
}
site = global.Site = {};
site.controllers = {};
site.actions = {};
site.load = function (name) {
var keys = name.split(".");
var c = keys[0];
var cs = this.controllers;
var as = this.actions;
var i;
if (cs.hasOwnProperty(c)) {
for (i =0 ; i < cs[c].length; i++) {
cs[c][i].call();
}
}
if (keys.length > 1 && as.hasOwnProperty(name)) {
for (i =0 ; i < as[name].length; i++) {
as[name][i].call();
}
}
};
site.add = function (name, fn) {
var keys = name.split(".");
var lv = keys.length > 1 ? this.actions : this.controllers;
if (!lv.hasOwnProperty(name)) {
lv[name] = [fn];
} else {
lv[name].push(fn);
}
};
})(window);
Run Code Online (Sandbox Code Playgroud)
app/views/layouts/application.html.erb
<body>
<script>
$(document).on("ready page:load", function () {
Site.load('<%= controller_name %>.<%= action_name %>');
}
</script>
<%= yield %>
</body>
Run Code Online (Sandbox Code Playgroud)
这是一个有趣的视频,关于为您可能喜欢观看的单页应用程序加载 javascript、css 和其他资产。
OSCON 2014:Instagram.com 的运作方式;皮特·亨特
https://www.youtube.com/watch?v=VkTCL6Nqm6Y