Rails 4:如何在涡轮链接中使用$(document).ready()

我在我的Rails 4应用程序中遇到了一个问题,而试图组织JS文件“Rails的方式”。他们以前分散在不同的观点。我将它们组织到单独的文件中,并使用资产管道编译它们。然而,我刚刚了解到,当涡轮链接被打开时,jQuery的“ready”事件不会在后续点击时触发。当你第一次加载一个页面时,它就工作了。但是当你点击一个链接时,ready( function($) {内的任何东西都不会被执行(因为页面实际上不会再次加载)。很好的解释:在这里

所以我的问题是:什么是确保jQuery事件在涡轮链接打开时正常工作的正确方法?您是否将脚本包装在特定于rails的侦听器中?或者也许rails有某种魔力,使它变得不必要?文档对这应该如何工作有点模糊,特别是关于通过manifest(s)加载多个文件,如application.js。

176789 次浏览
这是我所做的… CoffeeScript: < / p >
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), page:load会变成turbolinks:load,甚至会在初始加载时被触发。所以我们可以这样做:

$(document).on('turbolinks:load', function() {


...your javascript goes here...


});

或者使用

$(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

我刚知道另一个解决这个问题的方法。如果你加载jquery-turbolinks宝石,它会将Rails Turbolinks事件绑定到document.ready事件上,这样你就可以按照通常的方式编写jQuery了。你只需要在js manifest文件中的jquery之后添加jquery.turbolinks(默认为application.js)。

注意:请参阅@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

$(document).on('ready page:load', function () {
// Actions to do
});
< p > 编辑 < br > 如果你将委托事件绑定到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事件上。

Rails 4文档中找到了这个,类似于DemoZluk的解决方案,但略短:

$(document).on 'page:change', ->
# Actions to do

$(document).on('page:change', function () {
// Actions to do
});

如果你有调用$(document).ready()的外部脚本,或者如果你懒得重写所有现有的JavaScript,那么这个gem允许你继续使用TurboLinks: https://github.com/kossnocorp/jquery.turbolinks中的$(document).ready()

与其使用变量保存“ready”函数并将其绑定到事件,不如在page:load触发时触发ready事件。

$(document).on('page:load', function() {
$(document).trigger('ready');
});

以下是我所做的,以确保事情不会执行两次:

$(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")行为出乎意料——特别是如果你在开发中。

我发现下面的文章对我来说很有用,并详细说明了以下用法:

var load_this_javascript = function() {
// do some things
}
$(document).ready(load_this_javascript)
$(window).bind('page:change', load_this_javascript)

首先,安装jquery-turbolinks gem。然后,不要忘记将包含的Javascript文件从application.html.erb主体的末尾移动到它的<head>

就像这里描述一样,如果你出于速度优化的原因将应用程序javascript链接放在页脚中,你将需要将它移动到标签中,以便它在标签中的内容之前加载。这个解决方案对我很有效。

我想我应该把这个留给那些升级到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

测试了这么多解决方案,最终得出了这个结论。 你的代码肯定不会被调用两次。

      var has_loaded=false;
var ready = function() {
if(!has_loaded){
has_loaded=true;
           

// YOURJS here
}
}


$(document).ready(ready);
$(document).bind('page:change', ready);

根据新的rails指南,正确的方法是这样做:

$(document).on('turbolinks:load', function() {
console.log('(document).turbolinks:load')
});

或者在coffeescript中:

$(document).on "turbolinks:load", ->
alert "page has loaded!"

不监听事件$(document).ready,只会触发一个事件。没有意外,不需要使用jquery.turbolinks宝石。

这不仅适用于rails 5,而且适用于rails 4.2及以上版本。

以上这些都不适合我,我没有使用jQuery的$(document)来解决这个问题。ready,但使用addEventListener代替。

document.addEventListener("turbolinks:load", function() {
// do something
});
$(document).ready(ready)


$(document).on('turbolinks:load', ready)

你必须使用:

document.addEventListener("turbolinks:load", function() {
// your code here
})

来自turbolinks,博士

$(document).on 'ready turbolinks:load', ->
console.log '(document).turbolinks:load'

我通常为我的rails项目做以下工作:

application.js

function onInit(callback){
$(document).ready(callback);
$(document).on('page:load', callback);
}

然后在其余的.js文件中,我不使用$(function (){}),而是调用onInit(function(){})

我发现我的函数在使用readyturbolinks: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);
};

这样,如果支持涡轮链接,您的函数就不会加倍!