首页 文章

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

提问于
浏览
405

我试图组织JS文件"the rails way"时,在我的Rails 4应用程序中遇到了一个问题 . 他们以前分散在不同的观点中 . 我将它们组织成单独的文件,并使用资产管道进行编译 . 但是,我刚刚了解到,当启用turbo-linked时,jQuery 's 1180518 event doesn' t会触发后续点击 . 第一次加载页面时它可以工作 . 但是当你点击一个链接时, ready( function($) { 中的任何内容实际上都会重新加载't get executed (because the page doesn' . 好解释:here .

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

19 回答

  • 2

    根据新的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 宝石 .

    这适用于导轨4.2及以上,而不仅仅是导轨5 .

  • 0

    NOTE: See @SDP's answer for a clean, built-in solution

    我把它固定如下:

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

    以上都不适用于我,我通过不使用jQuery的$(document).ready来解决这个问题,但是使用addEventListener .

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

    要么使用

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

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

    而不是使用变量来保存"ready"函数并将其绑定到事件,您可能希望在 page:load 触发时触发 ready 事件 .

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

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

    $(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") 本身表现出意外 - 特别是如果你正在开发中 .

  • 90

    这就是我做的...... CoffeeScript:

    ready = ->
    
      ...your coffeescript goes here...
    
    $(document).ready(ready)
    $(document).on('page:load', ready)
    

    最后一行侦听页面加载,这是turbo链接将触发的内容 .

    Edit ...添加Javascript版本(每个请求):

    var ready;
    ready = function() {
    
      ...your javascript goes here...
    
    };
    
    $(document).ready(ready);
    $(document).on('page:load', ready);
    

    Edit 2 ...对于Rails 5(Turbolinks 5) page:load 变为 turbolinks:load ,甚至会在初始加载时触发 . 所以我们可以做到以下几点:

    $(document).on('turbolinks:load', function() {
    
      ...your javascript goes here...
    
    });
    
  • 73

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

  • 541

    最近我找到了最简洁易懂的处理方式:

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

    OR

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

    EDIT
    如果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 事件 .

  • 1

    Rails 4 documentation中找到了这个,类似于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

  • 2

    我发现以下article对我来说非常有用,并详细介绍了以下内容的使用方法:

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

    我想我会把这个保留在这里升级到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

  • 10

    你必须使用:

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

    from turbolinks doc .

  • 2
    $(document).ready(ready)  
    
    $(document).on('turbolinks:load', ready)
    
  • 0
    <%= link_to 'Edit', edit_article_path(article), 'data-no-turbolink' => true %>
    

    也许你可以像这样使用“准备好”,就像关闭你的turbolink一样 .

  • 198

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

    作为described here,如果您已将应用程序javascript链接放在页脚中以达到速度优化的原因,则需要将其移动到标记中,以便在标记中的内容之前加载 . 这个解决方案对我有用 .

  • 234

    经过测试,这么多解决方案终于来了 . 这很多代码绝对不会被调用两次 .

    var has_loaded=false;
          var ready = function() {
            if(!has_loaded){
              has_loaded=true;
               
              // YOURJS here
            }
          }
    
          $(document).ready(ready);
          $(document).bind('page:change', ready);
    
  • 8

    我通常为我的rails 4项目做以下事情:

    application.js

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

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

相关问题