-
Notifications
You must be signed in to change notification settings - Fork 11
/
03-templates.md.erb
295 lines (218 loc) · 12.7 KB
/
03-templates.md.erb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
---
title: Templates
slug: templates
date: 0003/01/01
number: 3
points: 1
photoUrl: http://www.flickr.com/photos/73449134@N04/8194499092/
photoAuthor: Mike Lewinski
contents: Meteorのテンプレート言語、Spacebars の学習。|三つのテンプレートの作成|Meteor マネージャの仕組み.|静的データを使った基本構造のプロトタイプを動かす
paragraphs: 46
version: 1.7
---
Meteor での開発を簡単にするため、私たちはアウトサイドインアプローチを用いることになります。
要するに、私たちは最初にイマイチな HTML と JavaScript で外側の骨組みを作り、
それから後でアプリが内側で動くように繋いでいきます。
つまり、この章では `/client ` ディレクトリの内側で何が起きるのかに関心を払うだけとなります。
では、/client ディレクトリの中に main.html という新しいファイルを作って、次のようなコードを書き込みましょう:
~~~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>
~~~
<%= caption "client/main.html" %>
これは アプリにメイン部分のテンプレートになります。
ご覧のように、`{{> postsList}} `タグ以外はすべて HTML です。
`{{> postsList}}` タグは、これから見ていく postsList テンプレートの挿入場所となります。
では、いくつかテンプレートを作っていきましょう。
### Meteor テンプレート
基本的に、ソーシャルニュースサイトは投稿のリストによって構成されています。
私たちはまさにそのようにテンプレートを作っていきます。
では、`/client` の中に `/templates` ディレクトリを作りましょう。
私たちは `/views` ディレクトリの中にすべてのテンプレートを置くことになります。
`/views` ディレクトリ内を整理したいので、投稿に関連したテンプレート用に、`/views` 内に `/posts`ディレクトリ を作ります。
<% note do %>
### ファイル検索機能
Meteor は素晴らしいことにファイルを探してくれます。
`/client` ディレクトリ内のどこにコードを入れようと、Meteor はコードを見つけだし確実にコンパイルします。
つまり、JavaScript や CSS にインクルードパスを記述する必要はありません。
また、同じディレクトリにすべてのファイルを置くこともできます。
さらには、同じファイルにすべてのコードを置くこともできます。
しかし、Meteor はすべてのコードを小さくした1つのファイルにコンパイルしてしまうので、
ファイル内をきちんと整理して、きれいなファイル構造にすると良いでしょう。
<% end %>
これから2つのテンプレートを作っていきます。
`client/views/posts` の中に `posts_list.html` を作ります
~~~html
<template name="postsList">
<div class="posts">
{{#each posts}}
{{> postItem}}
{{/each}}
</div>
</template>
~~~
<%= caption "client/templates/posts/posts_list.html" %>
次に `post_item.html` を作ります。
~~~html
<template name="postItem">
<div class="post">
<div class="post-content">
<h3><a href="{{url}}">{{title}}</a><span>{{domain}}</span></h3>
</div>
</div>
</template>
~~~
<%= caption "client/templates/posts/post_item.html" %>
テンプレート要素の `name="postsList"` 属性に注目してください。
この name はテンプレートの場所を Meteor に把握させるために使います。
(*実ファイル名* は関連しないことに注意してください)。
ここで Meteor のテンプレートシステム、**Spacebars** について紹介します。
Spacebars はシンプルな HTML に、3つ付け加えます: *内部テンプレート(inclusions)* と *式* とブロックヘルパーです。
*内部テンプレート* では `{{> templateName}}` 構文を使い、
構文記述箇所を同じ名前(今回は `postItem`)のテンプレートと置き換えるよう Meteor に指示します。
*式* は`{{title}}`と記述し、カレントオブジェクトのプロパティを呼び出すか、
テンプレートマージャーで定義されている後述するテンプレートヘルパーの値を返します。
最後に、ブロックヘルパーはテンプレートのフローをコントロールする特別なタグで、
`{{#each}}…{{/each}}` や `{{#if}}…{{/if}}` のように使います。
<% note do %>
### 他の機能について
`Spacebars` について更に学びたい場合は、[Spacebars ドキュメンテーション](https://github.com/meteor/meteor/blob/devel/packages/spacebars/README.md)を参照ください。
<% end %>
この知識が備わると、ここでどんなことが起こっているのか簡単に理解することができます
最初に `postsList` テンプレートについてですが、`{{#each}}…{{/each}}` ブロックヘルパーを使い `posts` オブジェクトに繰り返し処理を行っています。
繰り返し毎に、`postItem` テンプレートをインクルードしています。
あれ?`posts` オブジェクトはどこからやって来たんだろう?
いい質問です。
それは実際のところ、**テンプレートヘルパー** からやって来ており、動的に書き換わる値と考えて貰えばいいかと思います。
`postItem` テンプレート自体は簡単です。三つの式を使っています。: `{{url}}` と `{{title}}`は 文書のプロパティを返し, `{{domain}}` はテンプレートヘルパーを呼び出します。
### テンプレートヘルパー
ここまで私たちは Spacebars について取り組みました。
Spacebars はいくつかのタグを散りばめられた HTML です。
PHP のような他の言語と違って(あるいは、JavaScript が含まれた通常の HTML ページでさえ)、
Meteor はテンプレートと他のロジックを分離させます。
テンプレート自体が分離させるわけではありません。
テンプレートをうまく使うには、**ヘルパー**が必要です。
このヘルパーは料理ををウェイター(テンプレート)に渡す前に、生の食材(データ)をとってきて、調理をするシェフのようなものと見なすことができます。
言い換えると、テンプレートの役割は変数を表示をすることや変数をループすることに限定されますが、
ヘルパーはそれぞれの変数に値を割り当てる役割を果たしています。
<% note do %>
### コントローラー?
テンプレートヘルパーを含むファイルは、一種のコントローラとしての考えることはできるかもしれません。
しかし、あいまいな言い方ですが(少なくてもMVCにおける)コントローラとは、
わずかに異なる役割を持っています。
ですので我々は用語による分類をやめることに決めました。
このテンプレートに添えるjavaScriptコードについて話す場合は、
単純に、「テンプレートのヘルパー」もしくは「テンプレートのロジック」ということです。
<% end %>
物事をシンプルに保つために、我々は、テンプレートの後に
ヘルパーを含むファイル命名規則を採用しますが(訳間違い?命名規則が違うような)
**.js**の拡張子を持ちます。それでは、`/client/templates/posts`内に`posts_list.js`を作成してみましょう。
最初のヘルパーを作成しましょう。
~~~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
});
~~~
<%= caption "client/templates/posts/posts_list.js" %>
正しくできたら、ブラウザでは次のように表示されているでしょう。
<%= screenshot "3-1", "Our first templates with static data" %>
私たちはここで2つのことをしています。
まず1つめに `postsData` 配列の中でダミーの試作データを設定しています。
通常、データはデータベースからやって来るのですが、
この点は次の章で学びますので、今は静的データを使って「ごまかして」います。
2つめに、私たち Meteorの `Template.postsList.helpers()`関数を使って、 postsData 配列を返すだけの `posts` を呼び出すテンプレートヘルパーに定義しています。
覚えているでしょうか? `postsList` テンプレートで使う`posts`です。
~~~html
<template name="postsList">
<div class="posts">
{{#each posts}}
{{> postItem}}
{{/each}}
</div>
</template>
~~~
<%= caption "client/templates/posts/posts_list.html" %>
`posts`ヘルパーを定義すると、私たちのテンプレートは` postItem`テンプレートに内に含まれる各オブジェクトを`postsData`配列を反復処理して
渡すことができるようになりますので、このテンプレートは、
使用可能になったことを意味します。
<%= commit "3-1", "Added basic posts list template and static data." %>
### `domain` ヘルパー
同様に、`postItem`テンプレートのロジックを保持するために、
` post_item.js`を作成します:
~~~js
Template.postItem.helpers({
domain: function() {
var a = document.createElement('a');
a.href = this.url;
return a.hostname;
}
});
~~~
<%= caption "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.
<%= screenshot "3-2", "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.title` 、`this.url`を返すことで、
正しい値が返るかが理解できたかと思います。
<%= commit "3-2", "Setup a `domain` helper on the `postItem`." %>
<% note do %>
### JavaScript マジック
Meter固有の方法ではありません。
このjavaScriptマジックを簡単に説明すると、
まず、メモリ上にHTML要素である空のアンカー (a 要素) を作成します。
`href`属性に投稿情報のURLを渡します。
(先ほど示したように`this`にはオブジェクトが正しく設定されています)
最後に`a` 要素には `hostname`プロパティを使ってURLから
ドメイン名だけを取得します。
<% end %>
ここまで理解ができたら、ブラウザで 投稿 のリストを見ることができるでしょう。
このリストは単なる静的データなので、まだ Meteor のリアルタイムに関する機能を使っていません。
次の章ではデータを変化させる方法を見て行きましょう!
<% note do %>
### Hot Code リロード
ファイル変更の際に手動でブラウザをリロードをする必要がないことに
お気づきでしょうか。
これは Meteor がプロジェクトディレクトリ内のすべてのファイルを読み込んで、
変更点を見つけると自動的にブラウザを再読み込みするためです。
Meteor のホットコードリロードはとてもスマートで、コードとアプリの2状態をリフレッシュします!
<% end %>