ラウティング

ラウティング(Routing = アメリカ英語読みはルーティングよりもラウティングが近い)は、シングルページアプリケーション(SPA)を作るための仕組みです。他のページに行く時に、フルにブラウザをリフレッシュしなくても済むアプリケーションを実現することができます。

この機能を使うと、各ページをブックマークしたり、ブラウザの履歴の機能はそのままに、シームレスなナビゲーションが可能になります。

Mithrilは、ラウティングに関して、3種類の異なるサポートを提供します:

  • ラウトのリストの定義
  • ソースコードによる、ラウト間のリダイレクト
  • テンプレート内でリンクを作ると、透過的であまり主張しないリンクが作成できる

ラウトの定義

ラウトを定義する時は、ホストとなるDOM要素と、デフォルトのラウト、あとは遷移する可能性のあるラウトとそれをレンダリングするためのモジュールのキー・バリューのマップが必要となります。

次のサンプルは、<body>のレンダリングをする、3つのラウトを定義しています。homelogindashboardはそれぞれモジュールです。どのようにモジュールを定義するか見ていきましょう。

m.route(document.body, "/", {
    "/": home,
    "/login": login,
    "/dashboard": dashboard,
});

:を前に付いた単語を書くことで、ラウトに引数を設定することができます。

次のサンプルはuserIDパラメータを取るラウトです。

//サンプルモジュール
var dashboard = {
    controller: function() {
        return {id: m.route.param("userID")};
    },
    view: function(controller) {
        return m("div", controller.id);
    }
}

//#記号から始まるラウトを使用するための設定
m.route.mode = "hash";

//ラウトの定義
m.route(document.body, "/dashboard/johndoe", {
    "/dashboard/:userID": dashboard
});

これを実行すると、http://server/#/dashboard/johndoeにリダイレクトして、下記のタグを挿入します:

<body>johndoe</body>

上記のサンプルのdashboardはモジュールです。モジュールはcontrollerプロパティとviewプロパティを持ちます。URLがラウトにマッチすると、対応するモジュールのコントローラがインスタンス化されて、引数としてビューに渡されます。

この場合、ひとつのラウトしかないため、アプリケーションはデフォルトのラウトの"/dashboard/johndoe"にリダイレクトして、フレームワーク内でm.mount(document.body, dashboard)が呼ばれます。

johndoeという文字列が:userIDパラメータに結び付けられます。このパラメータは、コントローラ内でm.route.param("userID")というAPI呼び出しをするとプログラムから参照できます。

m.route.modeプロパティを使うと、どのURLに対してラウティングの仕組みを実装するかを定義できます。これは必ずm.route呼び出しよりも先に設定しなければなりません。このプロパティには、"search"、"hash"、"pathname"のいづれかの文字列を設定できます。デフォルトは"search"です。

  • searchモードはクエリー文字列を利用します。このモードを使うと、名前付きのアンカー(例えば、<a href="#top">トップに戻る</a><a name="top"></a>)を使うことができますが、IE8の場合はhistory.pushStateのサポートがないため、ページリフレッシュが発生してしまいます。

    サンプルURL: http://server/?/path/to/page

  • hashモードはハッシュを使います。このモードは唯一、どのブラウザでもページリフレッシュが発生しません。しかし、このモードでは名前付きアンカーが使えなくなりますし、ブラウザの履歴のリストがサポートされません。

    サンプルURL: http://server/#/path/to/page

  • pathnameモードは特別な文字を含まないURLを許可します。しかし、このモードでブックマークとページリフレッシュをサポートするためには、サーバ側にも手を加える必要があります。このモードも、IE8でページリフレッシュが発生します。

    サンプルURL: http://server/path/to/page

    pathnameモードを使用するためのサーバ設定の中で、一番簡単な方法は、どのURLが要求されても同じコンテンツを返すようにする方法です。Apacheを使っている場合は、mod_rewriteを使用してURLの書き換えを行うことでできます。


リダイレクト

APIを使用して他のページにリダイレクトすることもできます。ラウトの定義のセクションのサンプルですでに使っています:

m.route("/dashboard/marysue");

このコードを実行すると、http://server/#/dashboard/marysueにリダイレクトします。


モードの抽象化

このメソッドを使うには、 config仮想エレメントのプロパティを使用します。サンプル:

//`config`の設定を使うことで、`href`内に'#'を書かなくてもよくなる。
m("a[href='/dashboard/alicesmith']", {config: m.route});

この書き方を使用すると、どのm.route.modeが選択されていたとしても、期待通りの実行結果が得られます。href属性の中に?#をハードコードするのではなく、常に上記のようなイディオムを使うのが良いプラクティスです。

仮想エレメントについての詳細は、m()のドキュメントを参照してください。


ラウティングのおける再描画のセマンティクス

デフォルトでは、ラウトの変更時にはすべてを破棄してテンプレートの再描画が行われます。この動作は、configのコンテキストオブジェクトのretainフラグ、もしくはm.redraw.strategy("diff")ヒントを使って変更することができます。