jstarted.com
JavaScript/HTML/CSSのノウハウや覚書を掲載するブログ
2015.1.29

非同期ページ遷移の古典的手法 - データバインディングにhashを利用する

Category:
Tips

非同期で動くUIというのは、AjaxやSPAといったコンテンツを構築する際には、よく要件に挙がってくるかと思います。

僕は業務では企業のサイトやキャンペーンサイトを作成することが多いので、Ajaxですら扱う機会はあまりないのですが、たまにそういうのを求められる機会があり、その実装方法についてこれまでも少しずつ調べてきました。

結論からいうとhashを使う方法がシンプルで簡潔に済む方法のようでした。aタグのhref属性に簡単に設定できますし、history apiを使用せずともブラウザの履歴に残るため、ユーザーにとっても慣れ親しんだ直感的なUIにすることができます。

データの変更を検知してUIを変更すること、もしくはその逆のことをデータバインディングというようです。 今回は、hashを利用したデータバインディングをどのように実装するのかについて、まとめてみたいと思います。

hashの変更にあわせてUIを変更する2つの方法

以下は今回の内容にあわせて作成したテスト用コードです。
ボタンを押すとその内容に応じてbodyの背景色が変更される仕組になっていますが、その制御にhashを用いています。

See the Pen Changing background-color width a URI anchor (use hashChange) by ykob (@ykob) on CodePen.

hashの切替を検知し、それに応じて何かしらの処理を走らせてUIを変更するのには、知る限り2つの方法があります。

  • setIntervalなどのタイマーを使って、常時ハッシュを監視する。
  • window.onhashchangeを使う。

それぞれの方法について、コードを交えて解説していきます。

タイマーを使ってハッシュの変更を監視する

setIntervalでは100ミリ秒間隔でjudgeColorChange()を実行し続けています。
このjudgeColorChange()内でhashを取得し、変更されたかどうかを判断して、bodyの背景色を変更しています。

var $body = $('body');
var thisColor = '';

// ハッシュの切替を監視する関数
var judgeColorChange = function() {
  var changeColor = location.hash.split('#')[1];
  if (changeColor == thisColor) return;
  $body.attr('class', changeColor);
  thisColor = changeColor;
};

// ボタンをクリックした際のイベント
$('button').on('click', function() {
  location.hash = $(this).attr('class');
});

// タイマーで常時監視する
setInterval(function() {
  judgeColorChange();
}, 100);

window.onhashchangeイベントを使用する

onhashchangeを使う場合、hashが切り替わったタイミングを勝手に検知してくれるので、実装はタイマーを使う方法よりもシンプルになります。

var $body = $('body');

// ハッシュの切替を監視する関数
var judgeColorChange = function() {
  var changeColor = location.hash.split('#')[1];
  $body.attr('class', changeColor);
};

// ボタンをクリックした際のイベント
$('button').on('click', function() {
  location.hash = $(this).attr('class');
});

// onhashchangeを使用し、ハッシュが変わったタイミングで関数を動作させる
window.onhashchange = function() {
  judgeColorChange();
};

いずれの場合も気をつけたいことは、ボタンをクリックした際の処理、hash変更を監視する処理、実際にUIを変更する処理は別々に記載し、どこか同一の処理にまとめてしまわないことです。

処理をまとめてしまってネストを深くしてしまうと、最初に実装するときには管理できるかもしれませんが、のちのち変更する場合や操作したいUIを増やしたい場合、もしくは同一のUI処理を別のイベントからも発生させたいときなどに、更新が煩雑になる恐れがあります。

逆に言えば、使い慣れたハッシュを利用し、各処理を細かく分けて管理することで、一見複雑に見える非同期のUI操作もかなり簡単に実装できるということです。もし応用できそうな事例がすぐ思い浮かぶ場合は、上記の方法を試してみてはいかがでしょうか。


また、実際にhashを使ってUIを制御しているサンプルを掲載した記事を書きました。

hash使用のデータバインディングの感覚がまだよくつかめないという方は、よく見かけるUIを介することで理解が深まるかもしれません。

jstarted.comはamazon.co.jpを宣伝しリンクすることによってサイトが紹介料を
獲得できる手段を提供することを目的に設定されたアフィリエイト宣伝プログラムである、
Amazonアソシエイト・プログラムの参加者です。

クリエイティブ・コモンズ・ライセンス
jstarted.com by yoichi kobayashi is licensed under a Creative Commons 表示 3.0 非移植 License.