実践入門 Ember.js

第3回 画面遷移(Routing)

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

前回はURLと画面表示の基礎を解説しました。今回はEmber.jsでの画面遷移について,前回の内容を踏まえた上でもう少し踏み込んだ解説をします。

Ember.jsの「画面遷移」とはページ全体を再描画するのではなく,画面を部分的に書き換える動きをします。これがどういうことかを,例えばヘッダとサイドメニュー,メインコンテンツの表示部分があるアプリケーションを例にあげて考えてみましょう。

サイドメニューをクリックしてメインコンテンツを切り替えるという挙動を考えた場合,一般的なWebサイトであれば画面遷移が発生しヘッダ・サイドメニューを含めた画面のすべてが再描画されることでしょう。その一方でEmber.jsアプリケーションの場合はメインコンテンツのみが書き換えられます。

さて,それではさっそく今回の解説を進めていきましょう。今回は次のようなEmber.jsアプリケーションの仕組みを理解することを目標にします。

前準備

  1. まずはEmber.jsを使うために必要なライブラリをダウンロードします。

  2. 次のindex.htmlapp.jsを作成します。

    index.html

    <!DOCTYPE html>
    <html>
      <head>
        <meta charset="utf-8" />
        <title>実践入門 Ember.js</title>
        <link rel="stylesheet" href="style.css">
        <script src="libs/jquery-2.1.3.min.js"></script>
        <script src="libs/handlebars-v2.0.0.js"></script>
        <script src="libs/ember.js"></script>
        <script src="app.js"></script>
      </head>
      <body>
      </body>
    </html>

    app.js

    App = Ember.Application.create();

    また,style.cssという名前で,中身は空のCSSファイルを作成してください。

  3. これらを以下のディレクトリ構成で配置します。

    .
    ├─⁠─ app.js
    ├─⁠─ index.html
    ├─⁠─ libs
    │    ├─⁠─ ember.js
    │    ├─⁠─ handlebars-v2.0.0.js
    │    └─⁠─ jquery-2.1.3.min.js
    └─⁠─ style.css

以降,特に指定のない場合,JavaScriptはapp.jsに,Handlebarsのテンプレートはindex.htmlのbodyタグの中に,CSSはstyle.cssに記述することにします。

Routing

前回の解説では,アプリケーションの画面1つひとつがRouteに対応していると解説しました。では,画面を部分的に書き換えるというのはどう実現すればよいのでしょうか?

実は,Ember.jsではRouteを階層化することができ,入れ子になった子のRouteを切り替えることで画面を部分的に更新できます。

まずはルーティングを定義しておきましょう。

App.Router.map(function() {
  this.resource('posts', function() {
    this.route('show', {path: '/:post_id'});
  });
});

あわせてテンプレートを定義しておきます。

<script type="text/x-handlebars">
  <header>
    <h1>Ember.js ブログ</h1>
  </header>

  {{outlet}}
</script>

<script type="text/x-handlebars" data-template-name="index">
  <div id="hello-message">ようこそ</div>

  {{link-to "記事を見る" "posts"}}
</script>

<script type="text/x-handlebars" data-template-name="posts">
  <aside id="sidebar">
    <ul>
      {{#each post in model}}
        <li>{{link-to post.title "posts.show" post}}</li>
      {{/each}}
    </ul>
  </aside>

  <main>
    {{outlet}}
  </main>
</script>

<script type="text/x-handlebars" data-template-name="posts/index">
  記事を選択してください。
</script>

<script type="text/x-handlebars" data-template-name="posts/show">
  <h2>{{model.title}}</h2>

  <pre>
    {{model.body}}
  </pre>
</script>

また,動作確認用のデータとRouteを定義します。ここではJavaScriptファイルの中にデータを埋め込みましたが,実際にアプリケーションを作成する際はサーバからデータを取得してくることになるでしょう。この方法については後ほど解説します。

// データ
var posts = [{
  id: 1,
  title: 'はじめての Ember.js',
  body: 'これから Ember.js を始めようという方向けの記事です。'
}, {
  id: 2,
  title: '公式サイトの歩き方',
  body: 'http://emberjs.com/ の解説です。'
}, {
  id: 3,
  title: '2.0 のロードマップ',
  body: 'Ember.js 2.0 のロードマップはこちらで公開されています。https://github.com/emberjs/rfcs/pull/15'
}];

// Route 定義

App.PostsRoute = Ember.Route.extend({
  model: function() {
    return posts;
  }
});

App.PostsShowRoute = Ember.Route.extend({
  model: function(params) {
    var id = Number(params.post_id);
    var posts = this.modelFor('posts');

    return posts.filter(function(post) {
      return post.id === id;
    })[0];
  }
});

見栄えを整えるために,CSSも作成しておきます。

html, body {
  margin: 0;
  color: #444;
}

header {
  padding: 0 10px;
  background-color: #e15e45;
  color: #fcfcfc;
  text-shadow: rgba(0, 0, 0, 0.8) 0 1px 0;
  box-shadow: 0 0 1px 1px rgba(0, 0, 0, 0.2) inset;
}

header h1 {
  margin: 0;
}

#sidebar {
  float: left;
  width: 200px;
  height: 300px;
  color: #ba6051;
  text-shadow: 0 1px #faeeec;
  border: 1px solid #ccc;
}

#sidebar ul {
  padding: 0;
  margin: 0;
  list-style: none;
}

#sidebar li {
  padding: 5px 10px;
}

#sidebar li a {
  display: inline-block;
  height: 25px;
  width: 100%;
  color: #ba6051;
  text-shadow: rgba(0, 0, 0, 0.8) 0 1px 0;
  padding: 10px 2px;
  text-decoration: none;
}

#sidebar li .active {
  background-color: #eae0e1;
}

main {
  margin-left: 200px;
  height: 300px;
  padding-left: 10px;
  background-color: #faf2f1;
  border-top: 1px solid #ccc;
  border-right: 1px solid #ccc;
  border-bottom: 1px solid #ccc;
}

main ul {
  padding: 0;
  margin: 0;
  list-style: none;
}

では,この状態でどのようなURLが定義されるのかEmber Inspectorを使って確認してみましょう※1)⁠

※1
Ember Inspector については,第1回をご参照ください。

著者プロフィール

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

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

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

コメント

コメントの記入