実践入門 Ember.js

第2回 URLと画面表示(RoutingとTemplates)

この記事を読むのに必要な時間:およそ 7 分

Routing

次は Routingを見ていきます。
RoutingはURLとアプリケーションの画面を対応付ける機能です。

例えば,⁠記事の編集ページを開いている」⁠設定のタブを開いている」といった状態をURLで表現することで,JavaScriptで複雑な状態管理をしなくてはいけない状況からプログラマを解放してくれます。

もちろんこれはユーザにとってもメリットがあります。アプリケーションの状態をURLで表現できることは,SPAであっても任意の画面をブックマークできることになります。

RESTfulなWebアプリケーションを設計する際と同様,Ember.jsでSPAを設計する際にはURLを意識するのがよいプラクティスと言えます。

Ember.jsはデフォルトではURLを#からはじまるフラグメントハッシュの形で提供します※5)⁠Webサーバが返したパスを起点にして,#/以下にEmber.jsアプリケーションのパスを構築します。

※5
オプションを指定することで#がつかないURLを提供し,history APIを介した画面遷移を行うよう設定できます。しかしその場合は,Webサーバ側でも対応する必要があるので今回は扱いません。公式ガイドのSpecifying the URL Typeを参照してください。

RoutingにはRouterRouteという2つの部品が登場します。それぞれについて,サンプルコードを用いて解説します。

Architecture

画像

ここではapp.jsindex.htmlを準備したばかりの状態から始めることにします。

app.js

App = Ember.Application.create();

// Router
App.Router.map(function() {
  this.route('welcome', {path: '/'});
});


// Route
App.WelcomeRoute = Ember.Route.extend({
  model: function() {
    return {
      name: 'さとう'
    };
  }
});

テンプレートはこちらです。index.htmlbodyタグの中に記述してください。

<script type="text/x-handlebars" data-template-name="welcome">
  こんにちは, {{name}} さん
</script>

では,これらについて順番に説明していきます。

Router

Routerは今ブラウザで表示しようとしているURLについて,対応するRouteを探し出す役割を担います。Router.map()メソッドの中でthis.route(route名, オプション)の形式でRouteとURLの対応づけを行います。

App.Router.map(function() {
  this.route('welcome', {path: '/'});
});

この例では,WelcomeRoute/というURLに対応付けています※6)⁠route名とは,Routeのクラス名からRouteを削って小文字にしたものです。今回の例だと,WelcomeRouteに対応するroute名はwelcomeです。※7)⁠

※6
this.routeメソッドとよく似た機能をもつthis.resourceというメソッドも存在します。Route階層化して定義できるのですが,this.routethis.resourceではそのときの挙動が異なります。これについては次回詳しく解説します。今すぐ知りたい方は公式ガイドの「Defining Your Routes」"RESOURCES"を参照してください。
※7
this.route("hello_world")のように複数単語からなるroute名をつけた場合,HelloWorldRouteに対応するroute名はhello_worldです。

もしURLとroute名が同じであれば,pathの指定を省略できます。

App.Router.map(function() {
  this.route('welcome');
});

この記述だと,#/welcomeというURLでアクセスされた場合WelcomeRouteが有効になります。

また,Routerはデフォルトで#/IndexRouteの対応を持っています。したがって{path: '/'}を省略した場合,IndexRouteを自分で定義することで#/の画面に表示するオブジェクトを用意できます(Templatesの例で取り上げたサンプルがまさにこれです)⁠

Route

Routerによって処理を引き渡されたRouteは,自身に関連付けられたモデルオブジェクトとテンプレートを使って画面を描画します※8)⁠

※8
実はこのタイミングでControllerViewというEmber.jsのコンポーネントも準備されます。これらについては別の回で詳しく解説するので今回は触れません。
App.WelcomeRoute = Ember.Route.extend({
  model: function() {
    return {
      name: 'さとう'
    };
  }
});

modelメソッドの戻り値がこのRouteに対応するモデルオブジェクトになります。Routeはモデルオブジェクトをテンプレートに渡して画面を描画します。このとき利用されるテンプレートはroute名と同じものが使われます。この例の場合は,data-template-name="welcome"のテンプレートが使われます。

通常だとモデルオブジェクトはサーバサイドのAPIを呼び出して取得したデータを利用することが多いのですが,この例ではサンプルとして固定のシンプルなオブジェクトを返しています。

デバッグオプション

さて,実際にアプリケーションを作成する際には画面の数だけRouteを作成することになります。そうすると,どんなRouteが定義されていて今どのRouteが有効になっているのか知りたくなることでしょう。

そんなときのために,Ember.jsにはRoutingをデバッグするためのオプションが用意されています。

app.jsの以下のように書き換えてください:

Before:

App = Ember.Application.create();

After:

App = Ember.Application.create({
 LOG_TRANSITIONS: true,
 LOG_VIEW_LOOKUPS: true
});
  • LOG_TRANSITIONS … Route間の遷移をログ出力します(参考: LOGGING ROUTE CHANGES
  • LOG_VIEW_LOOKUPS … 画面表示に使用するテンプレートをログ出力します(参考: LOG VIEW LOOKUPS

これらのデバッグオプションを有効にしておくことで,⁠なんだかわからないけど画面に何も表示されない」といった場合に調査のヒントにできます。

これで,開発者ツールのコンソールに次のようなメッセージが表示されるようになります。

画像

テンプレート

<script type="text/x-handlebars" data-template-name="welcome">
  こんにちは, {{name}} さん
</script>

Routemodelメソッドで返したオブジェクトを表示します。これは先ほどTemplatesの項で解説した通りです。

著者プロフィール

佐藤竜之介(さとうりゅうのすけ)

株式会社えにしテック所属。JavaScriptとRubyが好きなウェブ系プログラマ。オープンソースソフトウェアに強い関心がありEmber.jsにも数多くのパッチを送っている。

ブログ:http://tricknotes.hateblo.jp/
Twitter:@tricknotes

コメント

  • craete -> create

    デバッグオプションのAfterの箇所がTypoってます。

    App = Ember.Application.craete({
    (略)
    });
    ではなく
    App = Ember.Application.create({
    (略)
    });
    です。

    コピペして動かないので考えこんでしまいました(笑)

    Commented : #1   (2015/01/02, 19:38)

コメントの記入