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

我在试图组织JS文件“rails方式”时遇到了Rails 4应用程序中的一个问题。 他们以前分散在不同的意见。 我把它们组织成单独的文件,并用资产pipe道进行编译。 但是,我刚刚了解到,jQuery的“就绪”事件不会触发涡轮链接打开后续点击。 你第一次加载一个页面的作品。 但是当你点击一个链接时, ready( function($) {任何东西都不会被执行(因为页面实际上并没有再次加载)。

所以我的问题是:什么是正确的方式来确保jQuery事件正常运行,而涡轮链接? 你把脚本包装在一个Rails特定的监听器中吗? 或者,也许铁轨有一些魔法,使之不必要? 这个文档对于如何工作有些模糊,特别是通过像application.js这样的清单加载多个文件。

这是我做的… 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... }); 

我刚刚了解到解决这个问题的另一个select。 如果你加载了jquery-turbolinks gem,它会把Rails Turbolinks事件绑定到document.ready事件,所以你可以用通常的方式编写你的jQuery。 您只需在js清单文件(默认情况下为application.js )中的jquery后面添加jquery.turbolinks

最近我发现了最简单易懂的处理方法:

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

要么

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

编辑
如果委托事件绑定到document ,请确保将它们附加到ready函数之外,否则它们将在每个page:load上被反弹page:load事件(导致相同的函数被多次运行)。 例如,如果你有任何这样的电话:

 $(document).on 'ready page:load', -> ... $(document).on 'click', '.button', -> ... ... 

把他们从readyfunction,如下所示:

 $(document).on 'ready page:load', -> ... ... $(document).on 'click', '.button', -> ... 

绑定到document委托事件不需要绑定ready事件。

在Rails 4的文档中发现了这个,类似于DemoZluk的解决scheme,但略短一些:

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

根据新的导轨指南 ,正确的方法是执行以下操作:

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

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

我修正如下:

请确保在通过更改包含顺序包含其他应用程序相关的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'); }); 

以上都没有为我工作,我解决了这个不使用jQuery的$(document).ready,而是使用addEventListener。

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

而不是使用variables来保存“就绪”函数并将其绑定到事件上,您可能希望在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) 

我想我会离开这里为那些升级到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

要么使用

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

  <%= link_to 'Edit', edit_article_path(article), 'data-no-turbolink' => true %> 

也许你可以像这样使用“准备”,就像closures你的turbolink。

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

你必须使用:

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

从turbolinks文档 。

首先,安装jquery-turbolinksgem。 然后,不要忘记把你的application.html.erb包含Javascript文件移动到它的<head>

如此处所述 ,如果您为了速度优化原因而将应用程序JavaScript链接放在页脚中,则需要将其移动到标记中,以便在标记中的内容之前加载它。 这个解决scheme为我工作。

testing了这么多的解决scheme终于来到这个。 这很多你的代码是绝对不会被调用两次。

  var has_loaded=false; var ready = function() { if(!has_loaded){ has_loaded=true; // YOURJS here } } $(document).ready(ready); $(document).bind('page:change', ready); 
 $(document).on 'ready turbolinks:load', -> console.log '(document).turbolinks:load'