428

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

所以我的问题是:在 turbo-links 开启时,确保 jQuery 事件正常工作的正确方法是什么?您是否将脚本包装在特定于 Rails 的侦听器中?或者也许 Rails 有一些魔力让它变得不必要?文档对于这应该如何工作有点含糊,尤其是关于通过诸如 application.js 之类的清单加载多个文件。

4

19 回答 19

560

这就是我所做的...... 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)在初始加载page:loadturbolinks:load甚至会被触发。所以我们可以做到以下几点:

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

  ...your javascript goes here...

});
于 2013-09-12T17:21:20.170 回答
236

我刚刚了解到解决此问题的另一种选择。如果您加载gem jquery-turbolinks它会将 Rails Turbolinks 事件绑定到document.ready事件,以便您可以以通常的方式编写 jQuery。您只需在 js 清单文件中添加jquery.turbolinksjquery默认情况下:)application.js

于 2013-09-16T17:49:38.113 回答
201

最近我发现了最干净、最容易理解的处理方式:

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

或者

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

编辑
如果您已委托绑定到 的事件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事件上。

于 2013-11-07T11:01:10.217 回答
91

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

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

或者

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

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

于 2014-02-03T11:06:03.057 回答
81

根据新的rails guides,正确的方法是执行以下操作:

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

或者,在咖啡脚本中:

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

不要监听事件$(document).ready,只会触发一个事件。毫不奇怪,无需使用jquery.turbolinks gem。

这适用于 rails 4.2 及更高版本,不仅适用于 rails 5。

于 2016-07-19T11:59:21.850 回答
10

注意:请参阅@SDP 的答案以获得干净的内置解决方案

我将其修复如下:

通过更改包含顺序,确保在包含其他依赖于应用程序的 js 文件之前包含 application.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');
});
于 2013-10-28T15:20:39.913 回答
9

以上都不适合我,我通过不使用 jQuery 的 $(document).ready 解决了这个问题,而是使用 addEventListener。

document.addEventListener("turbolinks:load", function() {
  // do something
});
于 2016-09-13T12:05:45.043 回答
7
$(document).on 'ready turbolinks:load', ->
  console.log '(document).turbolinks:load'
于 2017-08-28T10:14:29.323 回答
5

你必须使用:

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

来自 turbolinks 文档

于 2017-06-18T00:13:21.307 回答
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

于 2013-09-12T17:50:47.927 回答
2

这是我为确保事情不会执行两次所做的工作:

$(document).on("page:change", function() {
     // ... init things, just do not bind events ...
     $(document).off("page:change");
});

我发现使用jquery-turbolinksgem 或组合$(document).ready$(document).on("page:load")/或单独使用$(document).on("page:change")的行为出乎意料 - 特别是如果您正在开发中。

于 2015-03-19T07:51:49.947 回答
2

您可能希望在触发readypage:load触发事件,而不是使用变量来保存“就绪”函数并将其绑定到事件。

$(document).on('page:load', function() {
  $(document).trigger('ready');
});
于 2014-11-25T18:45:25.763 回答
2

我发现以下文章对我很有用,并详细介绍了以下内容的使用:

var load_this_javascript = function() { 
  // do some things 
}
$(document).ready(load_this_javascript)
$(window).bind('page:change', load_this_javascript)
于 2015-10-21T14:54:02.520 回答
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

于 2016-07-01T03:13:13.397 回答
2
$(document).ready(ready)  

$(document).on('turbolinks:load', ready)
于 2016-10-05T11:51:12.050 回答
1

测试了这么多解决方案终于到了这个。这么多你的代码绝对不会被调用两次。

      var has_loaded=false;
      var ready = function() {
        if(!has_loaded){
          has_loaded=true;
           
          // YOURJS here
        }
      }

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

于 2016-07-01T10:04:14.350 回答
1

我通常为我的 rails 4 项目执行以下操作:

application.js

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

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

于 2018-02-16T18:49:46.947 回答
0

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

如此处所述,如果出于速度优化的原因将应用程序 javascript 链接放在页脚中,则需要将其移动到标签中,以便它在标签中的内容之前加载。这个解决方案对我有用。

于 2016-06-21T09:58:11.410 回答
0

我发现我的函数在使用函数时翻了一番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);
};

这样,如果支持 turbolinks,您的功能就不会翻倍!

于 2019-10-10T06:13:51.473 回答