中村@アールテクニカ
アールテクニカの中村です。
今回はjQuery Mobileのページ遷移について解説します。
jQuery Mobileのページ遷移の仕組み
通常HTMLでページ遷移する場合は、HTMLをロードし続いてリンクしているJavaScriptやスタイルシートなどをロードします。
このようなブラウザ標準の遷移ではトランジションエフェクトを適用することは出来ません。
そこでjQuery Mobileでは、以下のような処理を行いトランジションを実現します。
- 遷移先のHTMLをAJAXでロードし、bodyタグ配下のコンテンツをまるごと元ページのbody配下に非表示状態で追加する。
- 続いてフェードなどのエフェクトをかけつつ元ページのコンテンツは非表示に、遷移先コンテンツは表示状態に変更する。
- 最後に参照元コンテンツを削除する。
ちなみに、aタグの属性にrel="external"と記述すると通常のページ遷移を行います。
ページ遷移の問題点
jQuery Mobileでは、ページ遷移にトランジションエフェクトが適用できる一方、通常のページ遷移とは違い以下のような挙動となります。
- 最初に開いたページのJavaScriptやスタイルシートしかロードされない。
- 最初にページを開いたときのみonloadイベントが発生する。jQueryのreadyメソッドも同様。
そのため、静的なHTMLであれば問題はありませんが、JavaScriptにより動的にコンテンツを作成する場合は、通常のHTMLのようにページごとにロードするJavaScriptを分けていたり、onloadイベントやjQueryのreadyメソッドなどで初期化していると、HTMLを直接開いたときは正常に動作しますが、他のページから遷移してくると正常に動作しません。
これに気付き思った通りに実装できるまでに半日かかってしまいました。
以下の様にすることでトランジションを有効にしつつ各ページを動的に初期化できるようになりました。
- すべてのHTMLでロードするJavaScriptとスタイルシートは同じにしておく。
- 各HTMLページの最外側のdivにはdata-role="page"属性と全ページでユニークなIDを振っておく。
- ページが表示される直前にjQuery Mobile独自の'pagebeforeshow'イベントが発生するのでここで全ページ共通のページ初期化関数を呼ぶ。
- ページ初期化関数では、$.mobile.activePage.attr('id')でページIDを取得しページ毎の初期化処理を行う。
page1.html(遷移元ページ)
<html> <head> <script src="jquery.js"></script> <script src="jquery.mobile-1.4.5.min.js"></script> <script src="app.js"></script> </head> <body> <div id="page-1" data-role="page"> <a href="page2.html" data-transition="slide">page2</a> </div> </body> </html>
page2.html(遷移先ページ)
<html> <head> <script src="jquery.js"></script> <script src="jquery.mobile-1.4.5.min.js"></script> <script src="app.js"></script> </head> <body> <div id="page-1" data-role="page"> </div> </body> </html>
app.js (各ページ共通のJavaScript)
$(document).on('pagebeforeshow', function(event, ui) { initPage(); }); function initPage() { switch ($.mobile.activePage.attr('id')) { case 'page-1': { // ページ1の初期化処理 } break; case 'page-2': { // ページ2の初期化処理 } break; }; }
jQuery Mobileは非常に強力なライブラリではありますが、独自の処理や作法が多いためハマりどころも多いといえます。
まだjQuery Mobileの一部の機能しか使っていませんが、今後もノウハウを共有できればと思います。