我在Rails 4应用程序中遇到了一个问题,同时尝试组织JS文件“rails way”。他们以前分散在不同的观点中。我将它们组织成单独的文件,并使用资产管道进行编译。但是,我刚刚了解到,当打开turbo-linked时,jQuery的“就绪”事件不会触发后续点击。第一次加载页面时它可以工作。但是当您单击某个链接时,ready( function($) {
内的任何内容都将无法执行(因为该页面实际上并未再次加载)。好的解释:here。
所以我的问题是:在启用turbo-links时,确保jQuery事件正常工作的正确方法是什么?您是否将脚本包装在特定于Rails的侦听器中?或者也许rails有一些魔力让它变得不必要?文档对于它应该如何工作有点模糊,特别是关于通过像application.js这样的清单加载多个文件。
答案 0 :(得分:546)
这就是我做的...... CoffeeScript的:
ready = ->
...your coffeescript goes here...
$(document).ready(ready)
$(document).on('page:load', ready)
最后一行侦听页面加载,这是turbo链接将触发的内容。
修改 ...添加Javascript版本(按要求):
var ready;
ready = function() {
...your javascript goes here...
};
$(document).ready(ready);
$(document).on('page:load', ready);
编辑2 ...对于Rails 5(Turbolinks 5)page:load
变为turbolinks:load
,甚至会在初始加载时触发。所以我们可以做到以下几点:
$(document).on('turbolinks:load', function() {
...your javascript goes here...
});
答案 1 :(得分:235)
我刚学会了另一个解决这个问题的方法。如果你加载the jquery-turbolinks
gem它会将Rails Turbolinks事件绑定到document.ready
事件,这样你就可以用通常的方式编写你的jQuery。您只需在jquery.turbolinks
之后的js清单文件中添加jquery
(默认情况下为application.js
)。
答案 2 :(得分:201)
最近我找到了最简洁易懂的处理方式:
$(document).on 'ready page:load', ->
# Actions to do
或强>
$(document).on('ready page:load', function () {
// Actions to do
});
修改强>
如果delegated events绑定到document
,请确保将它们附加到ready
函数之外,否则它们会在每个page:load
事件中反弹(导致相同的函数)要多次运行)。例如,如果您有任何这样的调用:
$(document).on 'ready page:load', ->
...
$(document).on 'click', '.button', ->
...
...
将它们从ready
函数中取出,如下所示:
$(document).on 'ready page:load', ->
...
...
$(document).on 'click', '.button', ->
...
绑定到document
的委托事件不需要绑定在ready
事件上。
答案 3 :(得分:91)
在Rails 4 documentation中找到了这个,类似于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
答案 4 :(得分:77)
根据新的rails guides,正确的方法是执行以下操作:
$(document).on('turbolinks:load', function() {
console.log('(document).turbolinks:load')
});
或者,在coffeescript中:
$(document).on "turbolinks:load", ->
alert "page has loaded!"
不要听事件$(document).ready
,只会触发一个事件。没有惊喜,不需要使用 jquery.turbolinks gem。
这适用于导轨4.2及以上版本,而不仅仅是导轨5。
答案 5 :(得分:10)
注意:请参阅@ SDP的答案,了解干净的内置解决方案
我将其修复如下:
确保在包含其他应用程序相关js文件之前包含application.js,方法是更改include顺序,如下所示:
// 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');
});
答案 6 :(得分:8)
以上都不适用于我,我通过不使用jQuery' $(document).ready解决了这个问题,但改为使用addEventListener。
document.addEventListener("turbolinks:load", function() {
// do something
});
答案 7 :(得分:4)
$(document).on 'ready turbolinks:load', ->
console.log '(document).turbolinks:load'
答案 8 :(得分:4)
你必须使用:
document.addEventListener("turbolinks:load", function() {
// your code here
})
答案 9 :(得分:3)
使用
$(document).on "page:load", attachRatingHandler
或使用jQuery的.on函数来实现相同的效果
$(document).on 'click', 'span.star', attachRatingHandler
请点击此处了解详情:http://srbiv.github.io/2013/04/06/rails-4-my-first-run-in-with-turbolinks.html
答案 10 :(得分:2)
您可能希望在ready
触发时触发page:load
事件,而不是使用变量来保存“就绪”功能并将其绑定到事件。
$(document).on('page:load', function() {
$(document).trigger('ready');
});
答案 11 :(得分:2)
这是我为确保事情没有执行两次所做的工作:
$(document).on("page:change", function() {
// ... init things, just do not bind events ...
$(document).off("page:change");
});
我发现使用jquery-turbolinks
gem或合并$(document).ready
和$(document).on("page:load")
或使用$(document).on("page:change")
本身表现出色 - 特别是如果您正在开发中。
答案 12 :(得分:2)
我发现以下article对我很有用,并详细说明了以下内容的使用:
var load_this_javascript = function() {
// do some things
}
$(document).ready(load_this_javascript)
$(window).bind('page:change', load_this_javascript)
答案 13 :(得分:2)
我想我会把这个留给升级到Turbolinks 5的人:修复代码的最简单方法是:
var ready;
ready = function() {
// Your JS here
}
$(document).ready(ready);
$(document).on('page:load', ready)
为:
var ready;
ready = function() {
// Your JS here
}
$(document).on('turbolinks:load', ready);
参考:https://github.com/turbolinks/turbolinks/issues/9#issuecomment-184717346
答案 14 :(得分:0)
使用ready
和turbolinks:load
的函数时,我发现函数加倍,所以我使用了
var ready = function() {
// you code goes here
}
if (Turbolinks.supported == false) {
$(document).on('ready', ready);
};
if (Turbolinks.supported == true) {
$(document).on('turbolinks:load', ready);
};
这样,如果支持turbolinks,您的功能就不会加倍!
答案 15 :(得分:0)
我通常会为我的rails 4项目执行以下操作:
在application.js
function onInit(callback){
$(document).ready(callback);
$(document).on('page:load', callback);
}
然后在.js文件的其余部分,而不是使用$(function (){})
,我致电onInit(function(){})
答案 16 :(得分:0)
$(document).ready(ready)
$(document).on('turbolinks:load', ready)
答案 17 :(得分:0)
测试了这么多解决方案终于来了。 这很多代码绝对不会被调用两次。
var has_loaded=false;
var ready = function() {
if(!has_loaded){
has_loaded=true;
// YOURJS here
}
}
$(document).ready(ready);
$(document).bind('page:change', ready);
答案 18 :(得分:0)
首先,安装jquery-turbolinks
gem。然后,不要忘记将已包含的Javascript文件从application.html.erb
的正文移动到其<head>
。
作为described here,如果您已将应用程序javascript链接放在页脚中以实现速度优化,则需要将其移动到标记中,以便在标记中的内容之前加载。这个解决方案对我有用。