Rails 4:如何使用带有turbo-links的$(document).ready()

时间:2013-09-12 17:16:42

标签: javascript jquery ruby-on-rails-4 asset-pipeline turbolinks

我在Rails 4应用程序中遇到了一个问题,同时尝试组织JS文件“rails way”。他们以前分散在不同的观点中。我将它们组织成单独的文件,并使用资产管道进行编译。但是,我刚刚了解到,当打开turbo-linked时,jQuery的“就绪”事件不会触发后续点击。第一次加载页面时它可以工作。但是当您单击某个链接时,ready( function($) {内的任何内容都将无法执行(因为该页面实际上并未再次加载)。好的解释:here

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

19 个答案:

答案 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
})

from turbolinks doc

答案 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)

使用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,您的功能就不会加倍!

答案 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链接放在页脚中以实现速度优化,则需要将其移动到标记中,以便在标记中的内容之前加载。这个解决方案对我有用。