「Railsの方法」でJSファイルを整理しようとしているときに、Rails 4アプリケーションで問題に遭遇しました。それらは以前はさまざまな見解にまたがっていました。私はそれらを別々のファイルにまとめ、アセットパイプラインでコンパイルしました。しかし、ターボリンクがオンになっていると、その後のクリックでjQueryの "ready"イベントが発生しないことを私は学びました。あなたが最初にページをロードするとき、それは働きます。しかし、リンクをクリックしても、ready( function($) {
内のものは実行されません(実際にはページは再び読み込まれないため)。良い説明: ここ 。
だから私の質問は:ターボリンクがオンの間にjQueryイベントが正しく動作することを保証するための正しい方法は何ですか?スクリプトをRails固有のリスナーにラップしますか?それとも、Railsに不必要な魔法があるのでしょうか。特にapplication.jsのようなマニフェストを介して複数のファイルをロードすることに関して、ドキュメントはこれがどのように機能するべきかについて少しあいまいです。
私はちょうどこの問題を解決するためのもう一つの選択肢を知りました。 jquery-turbolinks
gem をロードするとRails Turbolinksイベントをdocument.ready
イベントにバインドするため、通常の方法でjQueryを作成できます。 jsマニフェストファイルのjquery
の直後にjquery.turbolinks
を追加するだけです(デフォルトではapplication.js
)。
これが私のしていることです... 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:load
はturbolinks:load
になり、初期ロード時にも起動されます。それで、私たちはただ以下をすることができます:
$(document).on('turbolinks:load', function() {
...your javascript goes here...
});
最近、私は最もクリーンで理解しやすい方法を見つけました。
$(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
イベントにバインドされる必要はありません。
これは 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
新しい 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以上でも動作します。
注:クリーンでビルトインの解決策については、@ 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');
});
上記のどれも私にはうまくいきません、私はjQueryの$(document).readyを使わずにaddEventListenerを使うことでこれを解決しました。
document.addEventListener("turbolinks:load", function() {
// do something
});
$(document).on 'ready turbolinks:load', ->
console.log '(document).turbolinks:load'
あなたが使用する必要があります:
document.addEventListener("turbolinks:load", function() {
// your code here
})
どちらを使う
$(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
私は次の 記事 を見つけました。これは私にとってとても役に立ち、次の使い方を詳しく述べています:
var load_this_javascript = function() {
// do some things
}
$(document).ready(load_this_javascript)
$(window).bind('page:change', load_this_javascript)
変数を使用して "ready"関数を保存してイベントにバインドする代わりに、page:load
がトリガーされるたびにready
イベントをトリガーすることをお勧めします。
$(document).on('page:load', function() {
$(document).trigger('ready');
});
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回実行されないようにするために行ったことです。
$(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")
を単独で使うことは意外にも振る舞います - 特にあなたが開発中の場合。
$(document).ready(ready)
$(document).on('turbolinks:load', ready)
私は私のRails 4プロジェクトのために通常以下をします:
application.js
内
function onInit(callback){
$(document).ready(callback);
$(document).on('page:load', callback);
}
それから残りの.jsファイルでは、$(function (){})
を使う代わりにonInit(function(){})
を呼び出します。
非常に多くの解決策がついにこれに至りました。これほど多くのコードは絶対に2回呼び出されることはありません。
var has_loaded=false;
var ready = function() {
if(!has_loaded){
has_loaded=true;
// YOURJS here
}
}
$(document).ready(ready);
$(document).bind('page:change', ready);
まず、jquery-turbolinks
gemをインストールしてください。それから、インクルードされたJavascriptファイルをapplication.html.erb
の本文の終わりからその<head>
に移動することを忘れないでください。
ここで説明されている のように、スピードの最適化のためにアプリケーションのJavaScriptリンクをフッターに入れた場合は、タグ内のコンテンツの前にロードするようにタグに移動する必要があります。この解決策は私のために働いた。