Templates

3

翻訳の進捗

本章で学ぶこと:

  • Meteorのテンプレート言語、Spacebars の学習。
  • 三つのテンプレートの作成
  • Meteor マネージャの仕組み.
  • 静的データを使った基本構造のプロトタイプを動かす
  •  Meteor での開発を簡単にするため、私たちはアウトサイドインアプローチを用いることになります。 要するに、私たちは最初にイマイチな HTML と JavaScript で外側の骨組みを作り、 それから後でアプリが内側で動くように繋いでいきます。

    つまり、この章では /client ディレクトリの内側で何が起きるのかに関心を払うだけとなります。

    では、/client ディレクトリの中に main.html という新しいファイルを作って、次のようなコードを書き込みましょう:

    <head>
      <title>Microscope</title>
    </head>
    <body>
      <div class="container">
        <header class="navbar navbar-default" role="navigation">
          <div class="navbar-header">
            <a class="navbar-brand" href="/">Microscope</a>
          </div>
        </header>
        <div id="main" class="row-fluid">
          {{> postsList}}
        </div>
      </div>
    </body>
    
    client/main.html

    これは アプリにメイン部分のテンプレートになります。 ご覧のように、{{> postsList}}タグ以外はすべて HTML です。 {{> postsList}} タグは、これから見ていく postsList テンプレートの挿入場所となります。 では、いくつかテンプレートを作っていきましょう。

    Meteor テンプレート

    基本的に、ソーシャルニュースサイトは投稿のリストによって構成されています。 私たちはまさにそのようにテンプレートを作っていきます。

    では、/client の中に /templates ディレクトリを作りましょう。 私たちは /views ディレクトリの中にすべてのテンプレートを置くことになります。  /views ディレクトリ内を整理したいので、投稿に関連したテンプレート用に、/views 内に /postsディレクトリ を作ります。

    ファイル検索機能

    Meteor は素晴らしいことにファイルを探してくれます。 /client ディレクトリ内のどこにコードを入れようと、Meteor はコードを見つけだし確実にコンパイルします。  つまり、JavaScript や CSS にインクルードパスを記述する必要はありません。

    また、同じディレクトリにすべてのファイルを置くこともできます。 さらには、同じファイルにすべてのコードを置くこともできます。

    しかし、Meteor はすべてのコードを小さくした1つのファイルにコンパイルしてしまうので、 ファイル内をきちんと整理して、きれいなファイル構造にすると良いでしょう。

    これから2つのテンプレートを作っていきます。  client/views/posts の中に posts_list.html を作ります

    <template name="postsList">
      <div class="posts">
        {{#each posts}}
          {{> postItem}}
        {{/each}}
      </div>
    </template>
    
    client/templates/posts/posts_list.html

    次に post_item.html を作ります。

    <template name="postItem">
      <div class="post">
        <div class="post-content">
          <h3><a href="{{url}}">{{title}}</a><span>{{domain}}</span></h3>
        </div>
      </div>
    </template>
    
    client/templates/posts/post_item.html

    テンプレート要素の name="postsList" 属性に注目してください。 この name はテンプレートの場所を Meteor に把握させるために使います。 (実ファイル名 は関連しないことに注意してください)。

    ここで Meteor のテンプレートシステム、Spacebars について紹介します。 Spacebars はシンプルな HTML に、3つ付け加えます: 内部テンプレート(inclusions) とブロックヘルパーです。

    内部テンプレート では {{> templateName}} 構文を使い、  構文記述箇所を同じ名前(今回は postItem)のテンプレートと置き換えるよう Meteor に指示します。

    {{title}}と記述し、カレントオブジェクトのプロパティを呼び出すか、  テンプレートマージャーで定義されている後述するテンプレートヘルパーの値を返します。

    最後に、ブロックヘルパーはテンプレートのフローをコントロールする特別なタグで、 {{#each}}…{{/each}}{{#if}}…{{/if}} のように使います。

    他の機能について

    Spacebars について更に学びたい場合は、Spacebars ドキュメンテーションを参照ください。

    この知識が備わると、ここでどんなことが起こっているのか簡単に理解することができます

     最初に postsList テンプレートについてですが、{{#each}}…{{/each}} ブロックヘルパーを使い posts オブジェクトに繰り返し処理を行っています。 繰り返し毎に、postItem テンプレートをインクルードしています。

    あれ?posts オブジェクトはどこからやって来たんだろう?  いい質問です。 それは実際のところ、テンプレートヘルパー からやって来ており、動的に書き換わる値と考えて貰えばいいかと思います。

    postItem テンプレート自体は簡単です。三つの式を使っています。: {{url}}{{title}}は 文書のプロパティを返し, {{domain}} はテンプレートヘルパーを呼び出します。

    テンプレートヘルパー

    ここまで私たちは Spacebars について取り組みました。 Spacebars はいくつかのタグを散りばめられた HTML です。 PHP のような他の言語と違って(あるいは、JavaScript が含まれた通常の HTML ページでさえ)、 Meteor はテンプレートと他のロジックを分離させます。 テンプレート自体が分離させるわけではありません。

    テンプレートをうまく使うには、ヘルパーが必要です。 このヘルパーは料理ををウェイター(テンプレート)に渡す前に、生の食材(データ)をとってきて、調理をするシェフのようなものと見なすことができます。

    言い換えると、テンプレートの役割は変数を表示をすることや変数をループすることに限定されますが、 ヘルパーはそれぞれの変数に値を割り当てる役割を果たしています。

    コントローラー?

    テンプレートヘルパーを含むファイルは、一種のコントローラとしての考えることはできるかもしれません。 しかし、あいまいな言い方ですが(少なくてもMVCにおける)コントローラとは、 わずかに異なる役割を持っています。

    ですので我々は用語による分類をやめることに決めました。 このテンプレートに添えるjavaScriptコードについて話す場合は、 単純に、「テンプレートのヘルパー」もしくは「テンプレートのロジック」ということです。

    物事をシンプルに保つために、我々は、テンプレートの後に ヘルパーを含むファイル命名規則を採用しますが(訳間違い?命名規則が違うような) .jsの拡張子を持ちます。それでは、/client/templates/posts内にposts_list.jsを作成してみましょう。 最初のヘルパーを作成しましょう。

    var postsData = [
      {
        title: 'Introducing Telescope',
        author: 'Sacha Greif',
        url: 'http://sachagreif.com/introducing-telescope/'
      },
      {
        title: 'Meteor',
        author: 'Tom Coleman',
        url: 'http://meteor.com'
      },
      {
        title: 'The Meteor Book',
        author: 'Tom Coleman',
        url: 'http://themeteorbook.com'
      }
    ];
    Template.postsList.helpers({
      posts: postsData
    });
    
    client/templates/posts/posts_list.js

    正しくできたら、ブラウザでは次のように表示されているでしょう。

    Our first templates with static data
    Our first templates with static data

    私たちはここで2つのことをしています。 まず1つめに postsData 配列の中でダミーの試作データを設定しています。 通常、データはデータベースからやって来るのですが、 この点は次の章で学びますので、今は静的データを使って「ごまかして」います。

    2つめに、私たち Meteorの Template.postsList.helpers()関数を使って、 postsData 配列を返すだけの posts を呼び出すテンプレートヘルパーに定義しています。

    覚えているでしょうか? postsList テンプレートで使うpostsです。 ~~~html ~~~

    client/templates/posts/posts_list.html

    postsヘルパーを定義すると、私たちのテンプレートはpostItemテンプレートに内に含まれる各オブジェクトをpostsData配列を反復処理して 渡すことができるようになりますので、このテンプレートは、 使用可能になったことを意味します。

    コミット 3-1

    Added basic posts list template and static data.

    domain ヘルパー

    同様に、postItemテンプレートのロジックを保持するために、 post_item.jsを作成します:

    Template.postItem.helpers({
      domain: function() {
        var a = document.createElement('a');
        a.href = this.url;
        return a.hostname;
      }
    });
    
    client/templates/posts/post_item.js

    This time our domain helper’s value is not an array, but an anonymous function. This pattern is much more common (and more useful) compared to our previous simplified dummy data example.

    Displaying domains for each links.
    Displaying domains for each links.

    domain ヘルパー はURLを取得し、JavaScriptマジックを使って、 ドメイン名を返します。しかしどうやってurlからドメイン部分を取得するんでしょう?

    その答えはposts_list.htmlテンプレートにあります。 {{#each}} ブロックヘルパーは配列から繰り返し処理だけではなく、 ブロック内部のthisに反復オブジェクトを設定するという処理も行っていたのです。

    つまり{{#each}}タグの間で投稿情報を順次 this に 割り当てていたのです。 このテンプレートヘルパー(post_item.js)が含まれることで、 できることを拡張してきます。

    今まさになぜ、this.urlが投稿情報のURLをちゃんと返せるか。 それ以上に、post_item.html テンプレート内で、{{title}} , {{url}}を使ってthis.titlethis.urlを返すことで、 正しい値が返るかが理解できたかと思います。

    コミット 3-2

    Setup a `domain` helper on the `postItem`.

    JavaScript マジック

    Meter固有の方法ではありません。 このjavaScriptマジックを簡単に説明すると、 まず、メモリ上にHTML要素である空のアンカー (a 要素) を作成します。

    href属性に投稿情報のURLを渡します。 (先ほど示したようにthisにはオブジェクトが正しく設定されています)

    最後にa 要素には hostnameプロパティを使ってURLから ドメイン名だけを取得します。

    ここまで理解ができたら、ブラウザで 投稿 のリストを見ることができるでしょう。 このリストは単なる静的データなので、まだ Meteor のリアルタイムに関する機能を使っていません。 次の章ではデータを変化させる方法を見て行きましょう!

    Hot Code リロード

    ファイル変更の際に手動でブラウザをリロードをする必要がないことに お気づきでしょうか。

    これは Meteor がプロジェクトディレクトリ内のすべてのファイルを読み込んで、  変更点を見つけると自動的にブラウザを再読み込みするためです。

    Meteor のホットコードリロードはとてもスマートで、コードとアプリの2状態をリフレッシュします!