我已修改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 ...
问题在于,我安装了turbolinks。当我在同一个控制器中导航时,turbolinks可以工作。但当我切换到另一个控制器时,turbolinks将执行完全重新加载。有什么方法可以解决这个问题吗?
答案 0 :(得分:12)
<强> Turbolinks 强>
Turbolinks获取HTML页面的<body>
,并使用Ajax对其进行更改,使<head>
区域保持不变。
如果您的<head>
保持不变,则此仅有效 - 否则如何保持不变?因此,在更改控制器页面/资产的意义上,您将拥有来完成整页更新而不使用Turbolinks(至少如果您使用Turbolinks而不进行黑客攻击)
我建议修复此问题的方法是更改特定于控制器的资产结构,特别是尽可能少地对<head>
区域进行更改。
-
Turbolinks Tracking
阅读Turbolinks documentation
后,您可以从控制器特定资产中删除turbolinks-data-track
选项中受益:
<%= javascript_include_tag controller_name, 'data-turbolinks-track' => false %>
您可以跟踪某些资产,例如application.js和application.css, 您要确保的内容始终是最新版本 Turbolinks会议。这是通过标记这些资产链接来完成的 data-turbolinks-track,如下:
<link href="/assets/application-9bd64a86adb3cd9ab3b16e9dca67a33a.css" rel="stylesheet" type="text/css" data-turbolinks-track>
如果这些资产更改了网址(嵌入了md5标记以确保这一点),则该网页将完整填写 重装而不是通过Turbolinks。这确保了所有 Turbolinks会话将始终使用您最新的JavaScript 和CSS。
-
您将从中受益的是使用controller_name
帮助程序(代替params[:controller]
):
<%= javascript_include_tag 'application', controller_name, 'data-turbolinks-track' => true %>
答案 1 :(得分:4)
将控制器特定的j放在body标签中。由于turbolinks不会触及html主体,因此每次访问页面时都会重新加载那段js代码。
在你的情况下
<body>
<%= javascript_include_tag params[:controller] %>
...
</body>
但是如果您的控制器js中有很多代码,您可能会注意到上面的解决方案非常耗时。因为当您访问该页面时,将重新加载该大块代码。那怎么处理呢?
■以下方法可能会导致某些jquery事件多次绑定。这是turbolinks的问题。阅读这篇文章http://staal.io/blog/2013/01/18/dangers-of-turbolinks/
基本上,当用户第一次访问您的站点时,您加载所有js代码,确保控制器特定的代码不会运行(分别将它们包装在函数中)并将它们保存在全局变量中,例如{{1} }。然后通过编写类似
的内容来触发特定于控制器的jsSite
身体标签中的。
这样,实际的控制器特定的js代码只加载一次并在需要时被触发。
<script>
$(document).on("ready page:load", function () {
Site.load('<%= controller_name %>');
}
</script>
app/assets/javascripts/site.js
将控制器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;
}
}
。例如,Site
users.js
app/assets/javascripts/site.js
你的application.js中的加载它们。
Site.add("users", function () {
// UserController related js code
}
app/assets/javascripts/site.js
然后在布局中触发控制器特定的js。
//= require jquery
//= require jquery_ujs
//= require turbolinks
//= require site
//= require_tree .
app/views/layouts/application.html.erb
只需修改<body>
<script>
$(document).on("page:load", function () {
Site.load('<%= controller_name %>');
}
</script>
<%= yield %>
</body>
和布局即可。我最后用以下片段结束了。
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);
app/views/layouts/application.html.erb
这是一个有趣的视频,关于为您可能想要观看的单页应用加载javascript,css和其他资源。
OSCON 2014:Instagram.com如何运作;皮特亨特