I ran into an issue in my Rails 4 app while trying to organize JS files "the rails way". They were previously scattered across different views. I organized them into separate files and compile them with the assets pipeline. However, I just learned that jQuery's "ready" event doesn't fire on subsequent clicks when turbo-linking is turned on. The first time you load a page it works. But when you click a link, anything inside the ready( function($) { won't get executed (because the page doesn't actually load again). Good explanation: here.
所以我的问题是:什么是确保jQuery事件在涡轮链接打开时正常工作的正确方法?您是否将脚本包装在特定于rails的侦听器中?或者也许rails有某种魔力,使它变得不必要?文档对这应该如何工作有点模糊,特别是关于通过manifest(s)加载多个文件,如application.js。
我是这么做的…
CoffeeScript:
ready = ->
...your coffeescript goes here...
$(document).ready(ready)
$(document).on('page:load', ready)
最后一行监听页面加载,这是什么涡轮链接将触发。
编辑……添加Javascript版本(每个请求):
var ready;
ready = function() {
...your javascript goes here...
};
$(document).ready(ready);
$(document).on('page:load', ready);
编辑2…对于Rails 5 (Turbolinks 5)页面:load变成了Turbolinks:load,甚至会在初始加载时触发。所以我们可以这样做:
$(document).on('turbolinks:load', function() {
...your javascript goes here...
});
注意:请参阅@SDP的答案,以获得一个干净的内置解决方案
我修改如下:
确保你在其他依赖于应用程序的js文件被包括之前,通过改变包括顺序,如下所示:
// in application.js - make sure `require_self` comes before `require_tree .`
//= require_self
//= require_tree .
在application.js中定义一个处理绑定的全局函数
// application.js
window.onLoad = function(callback) {
// binds ready event and turbolink page:load event
$(document).ready(callback);
$(document).on('page:load',callback);
};
现在你可以绑定如下内容:
// in coffee script:
onLoad ->
$('a.clickable').click =>
alert('link clicked!');
// equivalent in javascript:
onLoad(function() {
$('a.clickable').click(function() {
alert('link clicked');
});
最近,我发现了一种最简单易懂的处理方法:
$(document).on 'ready page:load', ->
# Actions to do
OR
$(document).on('ready page:load', function () {
// Actions to do
});
编辑
如果您已经将事件委托给文档绑定,请确保将它们附加在ready函数之外,否则它们将在每个页面上反弹:load事件(导致相同的函数多次运行)。例如,如果你有这样的电话:
$(document).on 'ready page:load', ->
...
$(document).on 'click', '.button', ->
...
...
将它们从ready函数中取出,像这样:
$(document).on 'ready page:load', ->
...
...
$(document).on 'click', '.button', ->
...
绑定到文档的委托事件不需要绑定到就绪事件上。
在Rails 4文档中找到了这个,类似于DemoZluk的解决方案,但略短:
$(document).on 'page:change', ->
# Actions to do
OR
$(document).on('page:change', function () {
// Actions to do
});
如果你有调用$(document).ready()的外部脚本,或者如果你不想重写所有现有的JavaScript,那么这个gem允许你继续使用$(document).ready()和TurboLinks: https://github.com/kossnocorp/jquery.turbolinks
我想我把这个留给那些升级到Turbolinks 5的人:修复代码的最简单的方法是从:
var ready;
ready = function() {
// Your JS here
}
$(document).ready(ready);
$(document).on('page:load', ready)
to:
var ready;
ready = function() {
// Your JS here
}
$(document).on('turbolinks:load', ready);
参考:https://github.com/turbolinks/turbolinks/issues/9 # issuecomment - 184717346
根据新的rails指南,正确的方法是这样做:
$(document).on('turbolinks:load', function() {
console.log('(document).turbolinks:load')
});
或者在coffeescript中:
$(document).on "turbolinks:load", ->
alert "page has loaded!"
不监听事件$(document)。就绪后,只会触发一个事件。没有惊喜,不需要使用jquery。turbolinks宝石。
这不仅适用于rails 5,而且适用于rails 4.2及以上版本。