環境
Rails5.2
jQuery3
はじめに
RailsではデフォルトでTurobLinksが有効になっており、RailsでJavaScriptを動かすと、WindowのLoadイベントが発火しないという問題がありました。
詳しくはこちら。
https://qiita.com/pyon_kiti_jp/items/8dd1e94ba13003cb4520
JavaScriptだけでなく、jQueryを使う場合でも、同じような問題が発生します。JavaScriptでは、documentオブジェクトを使い、パラーメータを、loadからturbolinks:loadに書き換えることで回避できました。jQueryにおいても、似たような方法で回避することができます。jQueryにおける回避方法について、書いてみました。
やったこと
画面をロードするとき(初回ロード、リロード共に)、jQueryで発火するイベントは、readyイベントになります。JavaScriptのloadイベントに該当するjQueryのイベントが、readyイベントということです。(※ VBでいう、Form_Loadです。)
Rails上で使うのではなく、jQuery単体で使う場合であれは、このような書き方になります。TurobLinksを意識することのない通常の書き方です。
jQuery(document).ready(function() {
console.log("NG");
})
しかし、Rails上でjQueryを使う場合(TurobLinksが有効になっている場合)は、初回の画面起動時には問題ないのですが、link_toで画面遷移を行うと、このイベントに入ってきてくれません。
この問題を回避するためには、次のように書き換える必要があります。
jQuery(document).on('turbolinks:load', function(){
console.log("OK");
})
readyイベントとonイベントの違い
jQueryには、画面をロードするタイミングで発火するイベントが2つあります。readyイベントとonイベントです。この2つのイベントは、発火するタイミングが微妙に異なります。発火する順番は、readyイベントが先に発火に、後発でonイベントが発火します。
-
readyイベント
画面のDOM要素が全てブラウザに読み込まれた後に発火します。 -
onイベント
readyイベントが発火した後、各種アセットファイルがブラウザに読み込まれた後に発火します。
アセットファイルが重たくて、ダウンロードに時間がかかる場合、onイベントを使うと、画面の表示に時間がかかるといった問題点が生じます。それに比べ、readyイベントを使うと、例えアセットファイルが重たくても、画面遷移がスムーズに行えている印象を与えることができます。(画面遷移が行われた後に、ダウンロードが発生するためで、決してアセットファイルのダウンロードが速くなっているわけではありません。)
TurobLinksを使っていない場合は、必要に応じて、readyイベントとonイベントを使い分けることができます。しかし、TurobLinksを使っている場合は、documentオブジェクトに対するイベントをしか取得することができず、windowオブジェクトに対するイベントが取得できないという制限が入ります。
JavaScriptでは、画面表示のときloadイベントが使われますが、jQueryの画面表示で使われのはonイベントで、loadイベントというのはjQueryにはありません。しかし、旧バージョンのjQuery3.0以前ではloadイベントが存在していた過去があります。それが、jQuery3.0より廃止され、onイベントに置き換わっています。
windowとdocumentの違い
表にまとめると次のようになります。
on | ready | |
---|---|---|
window | 〇(2番目) | × |
document | ×(TuboLinks有:〇) | 〇(1番目) |
表にある×印は、このような使い方はできませんという意味です。つまり、次のような使い方はできません。
TurboLinksを有効にして使う場合に限り、documentオブジェクトとonイベントの組み合わせで使われることになります。
// 使えません
jQuery(window).ready('load', function() {
console.log("NG");
})
// 使えません
jQuery(document).on('load', function(){
console.log("NG");
});
jQueryと$
jQuery()は $()と置き換えて記述することができます。$()はjQuery()の別名です。基本的にどちらを使ってもOKですが、jQuery()を使うことが推奨されているようです。
自身はまだ体験したことはありませんが、$()を使うと、他のライブラリを読み込んで使う場合、ライブラリの影響を受けて、$()が上書きされることがあり、想定外のトラブルが発生することがあるようです。特に、WordPressを使っているときは、$()を使ってはいけないということは有名なようです。
onイベントの雛形
画面遷移でonイベントを発火させるときの書き方は、1種類だけではありません。ググってみると、どうも、大きく3パターンに分かれるようです。もっと他の方法もあるかも分かりませんが、あったとしても恐らくマイナーな使い方だと思います。ググってヒットされる情報から推測すると、無名関数を使った方法が一般的なようです。
// 無名関数
jQuery(document).on('turbolinks:load', function(){
console.log("OK1");
})
// アロー関数
jQuery(document).on('turbolinks:load', () => {
console.log("OK2");
})
// 外部関数
jQuery(document).on('turbolinks:load', hoge);
function hoge() {
console.log("OK3");
}
readyイベントの雛形
Railsとは関係のないところで、jQueryを単体で使ったとき、画面遷移で発火するイベントは、readyイベントです。readyイベントの書き方も、ググってみると、書き方は1種類だけではなく、色々な書き方があるようです。なぜ、色々な書き方が存在しているのかといえば、部分的に省略して記述することができるからです。省略して記述できると、コーディング量が減り、時として便利ではありますが、反面、どの書き方が正解なのだろうかと、戸惑ってしまうことがあります。自分が調べた限りでは、readyイベントの書き方は、次の3種類に集約できるようです。
// 一番ノーマルな書き方
jQuery(document).ready(function() {
console.log("OK1");
})
// readyを省略
jQuery(function(){
console.log("OK2");
})
// documentを省略(非推奨)
jQuery().ready(function(){
console.log("OK3");
})
補足
Turbolinksを有効にしても、readyイベントが使えるようになるgemが提供されています。jquery-turbolinksというgemです。「え!、それ早く言ってよ。」というところかも分かりませんが、注意点があります。このgemを使うと、readyイベントが使えるようにはなるが、別の個所で不具合が発生する場合があるようです。一般的にはあまり使われないようです。