2015.1.29
非同期で動くUIというのは、AjaxやSPAといったコンテンツを構築する際には、よく要件に挙がってくるかと思います。
僕は業務では企業のサイトやキャンペーンサイトを作成することが多いので、Ajaxですら扱う機会はあまりないのですが、たまにそういうのを求められる機会があり、その実装方法についてこれまでも少しずつ調べてきました。
結論からいうとhashを使う方法がシンプルで簡潔に済む方法のようでした。aタグのhref属性に簡単に設定できますし、history apiを使用せずともブラウザの履歴に残るため、ユーザーにとっても慣れ親しんだ直感的なUIにすることができます。
データの変更を検知してUIを変更すること、もしくはその逆のことをデータバインディングというようです。 今回は、hashを利用したデータバインディングをどのように実装するのかについて、まとめてみたいと思います。
以下は今回の内容にあわせて作成したテスト用コードです。
ボタンを押すとその内容に応じてbodyの背景色が変更される仕組になっていますが、その制御にhashを用いています。
See the Pen Changing background-color width a URI anchor (use hashChange) by ykob (@ykob) on CodePen.
hashの切替を検知し、それに応じて何かしらの処理を走らせてUIを変更するのには、知る限り2つの方法があります。
それぞれの方法について、コードを交えて解説していきます。
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);
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操作もかなり簡単に実装できるということです。もし応用できそうな事例がすぐ思い浮かぶ場合は、上記の方法を試してみてはいかがでしょうか。