web-dev-qa-db-ja.com

Rails 4:ターボリンクで$(document).ready()を使う方法

「Railsの方法」でJSファイルを整理しようとしているときに、Rails 4アプリケーションで問題に遭遇しました。それらは以前はさまざまな見解にまたがっていました。私はそれらを別々のファイルにまとめ、アセットパイプラインでコンパイルしました。しかし、ターボリンクがオンになっていると、その後のクリックでjQueryの "ready"イベントが発生しないことを私は学びました。あなたが最初にページをロードするとき、それは働きます。しかし、リンクをクリックしても、ready( function($) {内のものは実行されません(実際にはページは再び読み込まれないため)。良い説明: ここ

だから私の質問は:ターボリンクがオンの間にjQueryイベントが正しく動作することを保証するための正しい方法は何ですか?スクリプトをRails固有のリスナーにラップしますか?それとも、Railsに不必要な魔法があるのでしょうか。特にapplication.jsのようなマニフェストを介して複数のファイルをロードすることに関して、ドキュメントはこれがどのように機能するべきかについて少しあいまいです。

411
emersonthis

私はちょうどこの問題を解決するためのもう一つの選択肢を知りました。 jquery-turbolinks gem をロードするとRails Turbolinksイベントをdocument.readyイベントにバインドするため、通常の方法でjQueryを作成できます。 jsマニフェストファイルのjqueryの直後にjquery.turbolinksを追加するだけです(デフォルトではapplication.js)。

235
emersonthis

これが私のしていることです... 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...

});
546
Meltemi

最近、私は最もクリーンで理解しやすい方法を見つけました。

$(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イベントにバインドされる必要はありません。

200
Artyom Tsoy

これは Rails 4のドキュメント で見つかりました。これはDemoZlukのソリューションと似ていますが、少し短くなっています。

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

OR

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

$(document).ready()を呼び出す外部スクリプトがある場合、または既存のJavaScriptをすべて書き直すことに煩わされない場合は、このgemを使用してTurboLinksで$(document).ready()を使い続けることができます。 https://github.com/kossnocorp/jquery.turbolinks

91
migu

新しい Railsガイド に従って、正しい方法は次のとおりです。

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

または、コーヒースクリプトでは:

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

イベント$(document).readyをリッスンしないでください。1つのイベントだけが発生します。驚くべきことではなく、 jquery.turbolinks gemを使う必要もありません。

これはRails 5だけでなくRails 4.2以上でも動作します。

76
vedant

注:クリーンでビルトインの解決策については、@ 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');
});
10
sled

上記のどれも私にはうまくいきません、私はjQueryの$(document).readyを使わずにaddEventListenerを使うことでこれを解決しました。

document.addEventListener("turbolinks:load", function() {
  // do something
});
8
RockL
$(document).on 'ready turbolinks:load', ->
  console.log '(document).turbolinks:load'
4
Sukeerthi Adiga

あなたが使用する必要があります:

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

turbolinksから -

どちらを使う

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

3
derekyau

私は次の 記事 を見つけました。これは私にとってとても役に立ち、次の使い方を詳しく述べています:

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

変数を使用して "ready"関数を保存してイベントにバインドする代わりに、page:loadがトリガーされるたびにreadyイベントをトリガーすることをお勧めします。

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

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

2
tirdadc

これは、物事が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")を単独で使うことは意外にも振る舞います - 特にあなたが開発中の場合。

2
Gray Kemmey
$(document).ready(ready)  

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

私は私のRails 4プロジェクトのために通常以下をします:

application.js

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

それから残りの.jsファイルでは、$(function (){})を使う代わりにonInit(function(){})を呼び出します。

0
muZk

非常に多くの解決策がついにこれに至りました。これほど多くのコードは絶対に2回呼び出されることはありません。

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

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

まず、jquery-turbolinks gemをインストールしてください。それから、インクルードされたJavascriptファイルをapplication.html.erbの本文の終わりからその<head>に移動することを忘れないでください。

ここで説明されている のように、スピードの最適化のためにアプリケーションのJavaScriptリンクをフッターに入れた場合は、タグ内のコンテンツの前にロードするようにタグに移動する必要があります。この解決策は私のために働いた。

0
Aboozar Rajabi