ブログトップ 記事一覧 ログイン 無料ブログ開設

へっぽこプログラマーの日記 RSSフィード Twitter

2012-04-05

そろそろjQuery Mobileでajaxを無効にしてるやつに一言いっておくか

| 22:06 |

jQuery Mobileでは、ページ遷移の際に自動的にajaxが利用されています。特に何もしなくても遷移先のページをajaxで取得してアニメーションをつけて遷移するというのがjQuery Mobileの大きな特徴のひとつになっています。

しかしながら、巷では、何か問題があるとすぐにこのajaxを無効にするという対処方法が蔓延しているようです。ちなみにajaxを無効にする方法というのは、以下のようなものを指します。


  • a要素やform要素に data-ajax="false" を指定する。
  • グローバル設定で $.mobile.ajaxEnabled = false; を設定する。

もちろん、このajaxの挙動を理解した上で、ajaxを無効にするという方法を取ることは何ら問題ないのですが、とにかく困ったらajaxを無効にするということが多いようです。

具体的には以下のようなケースが挙げられるでしょう。


  • ページ遷移が遅いからajaxを無効にする
  • Google AnalyticsやAdSenseを入れるためにajaxを無効にする
  • スクリプトが動かない、スタイルが効かないから無効にする
  • 何か問題があると取り敢えずajaxを無効にしてみる

(2012/04/12 追記)

次のパターンも注意が必要なのでこちらに載せておきます。

  • 同一ドメイン上に安全でないリソースがある可能性がある場合

これらのケースについて、個別に対処方法などを解説していきたいと思います。


ページ遷移が遅いからってajaxを無効にしない

よく誤解されがちなのが、ページ遷移が遅いという問題です。たしかに、Android端末では特にCSS周りの実装が怪しく、アニメーションがやばい感じですが、それを除けばajaxを有効にしたほうが確実に早いです。

なぜなら、ajaxでは遷移先のページの最初のdata-role="page"の要素のみを切り出して読み込むからです。head要素内ののscript要素やstyle要素は一切読み込まないため、余計なリクエストは発生しません(まあ、この読み込まないという部分が後述する問題にもなっていますが)。

アニメーションが遅いのであれば、アニメーションをオフにすれば良いだけなので、ajaxとは別に考えましょう。


アニメーションを無効にする

$(document).bind('mobileinit', function(){
  $.mobile.defaultPageTransition = 'none';  
});

また、リンクをタップしてからページ遷移するまで遅いという人は、vclickイベントでページを遷移するようにチューニングしてみると良いかもしれません。Webkit系のブラウザでは、clickイベントなどはdouble tapなどの判定のために、300msほどの待ち時間が発生するので、代わりにvclickイベント使えばすぐに反応するようになります。vclickイベントはtouchイベントとclickイベントを統合したjQuery Mobile仮想イベントです。


vclickイベントでページ遷移する

$(document).delegate('a', 'vclick', function(e){
  e.preventDefault();
  var link = $(this);
  $.mobile.changePage(link.attr('href'), {
    transition: link.jqmData('transition')
  });
});

(delegate自体が遅いとか、changePageの引数が足りないとかは自身でカスタマイズして使ってください)

あとは、ページ要素へのdata-dom-cache設定や、リンクへのdata-prefetch設定などもあるので、うまく使ってチューニングしてください。


Google AnalyticsやAdSenseを入れるためでもajaxを無効にしない

ページの遷移方法が、通常と異なるために、単純にコードやHTMLを貼りつけただけでは最初のページ以外ではうまく動作しません。これは、下記エントリで既に書いたので、参照してください。Google AdSenseは使ったことないので、なんとか自力で頑張ってください。


jQuery MobileでGoogle Analyticsを使う方法


スクリプトが動かない、スタイルが効かないからってajaxは無効にしない

遷移先のページをajaxで取得して、ページ要素のみを切り取るので、他の部分に記述したスクリプトやスタイルは読み込まれません。そのため、最初に読み込まれるページですべてのスクリプトやスタイルを読み込む必要があります。ページ表示時に発火するpageshowイベントやページのイニシャライズで1回だけ発生するpageinitイベントなど、ページ関連のイベントをうまく使ってください。


pageshow(ページ表示のたびに毎回発生)

$(document).delegate('#page1', 'pageshow', function(){
  // 情報の更新やトラッキングなど
});

pageinit(ページのイニシャライズで1回のみ発生)

$(document).delegate('#page1', 'pageinit', function(){
  // スクリプトによる静的要素の追加やイベントの登録など
});

また、ここで作成した全ページ共通のスクリプトやスタイルを、全ページに埋め込んでおいてください。なぜなら、どのページが最初に読み込まれるからわからないからです。途中のページでブラウザのリロードを実行しまうと、そこが基点になってしまいます。逆に、全ページに埋め込んでも、読み込まれるのは最初のページだけです。他にもどうしても、ページごとに書きたいという場合は、ページ要素の中にスクリプトを書くという手もあります。


スクリプトやスタイルをページ要素に含める

<div data-role="page">
  <script>
    // 何か
  </script>
</div>

何か問題があっても取り敢えずajaxを無効にしない

とりあえず、何か問題があったらバグだと早計する前に、挙動をひとつひとつ確認して対処しましょう。ajax無効にするのであれば、Twitter Bootstrapなどのデザインフレームワークだけを使うとか、もしくは一から作るとかしたほうが良いと思います。(jQuery Mobileはデザインフレームワークだけで使うには巨大なので)


(2012/04/12 追記)

同一ドメイン上に安全でないリソースがある可能性がある場合

ajaxによるページ遷移は、URLから実行することが可能なため、同一ドメイン上に安全でないリソースがある場合は注意が必要です。例えば、ユーザーが自由にアップロードできるフォルダがあるとか、共有ドメインを使ってる場合などです。そういう場合には、pagebeforeloadイベントを使ってチェックしましょう。

$(document).bind('pagebeforeload', function(e, data){
  
  var isValid = false;
  // ホワイトリストなどでajax遷移できるアドレスを制限する
  if ( !isValid ) {
    e.preventDefault();
    data.deferred.reject(data.absUrl, data.options);
  }
});

まぐまぐ 2012/04/06 15:46 ajax無効にする=デザインフレームワークだけ使うってことでは。。

pikoteapikotea 2012/04/06 16:07 コメントありがとうございます。jQuery Mobileをデザインフレームワークとして使うこともありますが、フレームワークが大きいので、そういう用途で利用するのであれば、他の選択肢も検討したほうが良いという意でした。(若干修正しました)

花火花火 2012/06/30 12:58 コメント失礼します。
jquerymobileで作り、動かしてみた所、pcではajaxが使えているのですが、iphoneで操作したとき動きません。
意図しないURLに飛んでいるようです;
「スクリプトが動かない、スタイルが効かないからってajaxは無効にしない」の項目に当てはまると思われるのですが、上記の解決方法が理解出来ません;;
なかなか他のサイトにも解決策が無いです。上記の解決策で理解できなかったら出来ないのでしょうか・・・?(×_×)

pikoteapikotea 2012/06/30 14:07 iPhoneのバージョンが古いというわけではないのですよね?
特殊なことをやっていなければきちんと動作するとは思いますが。。。

   2014/05/31 22:20 ページ間でID属性の重複が許されない欠陥仕様がある限り使い物にならないでしょ。

タイトルが気になった人タイトルが気になった人 2015/01/03 11:44 ブログ記事、ためになって、面白かった、
タイトルも気を引いて楽しかったけど、
自身のページへのPOST はどうしてもAjax 無効にしないと困るから
100%は同意できないタイトルでしたw

jQuery Mobile のブラウザURL 偽装っぽいことが出来るのは
よくわかったw
ある意味危ないね・・・もしもだけど問題があるのならば
ブラウザ側が対策しなくちゃね!