forked from DiscoverMeteor/DiscoverMeteor_Pl
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path03-templates.md.erb
231 lines (157 loc) · 10.8 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
---
title: Szablony
slug: templates
date: 0003/01/01
number: 3
contents: O Handlebars, języku szablonów Meteora.|Jak stworzyć pierwsze trzy szablony.|Jak działają managery Meteora.|Jak ukończyć prototyp aplikacji wyświetlający statyczne dane.
paragraphs: 46
---
Aby ułatwić wprowadzenie do Meteora, zaimplementujemy ogólny szkielet aplikacji i później przejdziemy do coraz bardziej szczegółowych zagadnień. Innymi słowy na początek zbudujemy szkielet HTML/JavaScript, następnie będziemy go podłączać etapami do kolejnych części Meteora.
Oznacza to, że w bieżącym rozdziale skoncentrujemy się wyłącznie na tym, co dzieje się w folderze `/client`.
Stwórzmy nowy plik o nazwie `main.html` w folderze `/client` i wstawmy do niego następujący kod:
~~~html
<head>
<title>Microscope</title>
</head>
<body>
<div class="container">
<header class="navbar">
<div class="navbar-inner">
<a class="brand" href="/">Microscope</a>
</div>
</header>
<div id="main" class="row-fluid">
{{> postsList}}
</div>
</div>
</body>
~~~
<%= caption "client/main.html" %>
Będzie to nasz główny szablon aplikacji. Jak widać jest to HTML z wyjątkiem taga `{{> postsList}}`, który jest miejscem wstawienia szablonu `postsList` jak wkrótce zobaczysz. Na teraz stwórzmy jeszcze kilka szablonów.
### Szablony Meteora
Jądrem serwisu wiadomości społecznościowych jest lista postów. Dokładnie w taki sposób zorganizujemy szablony.
Stwórzmy folder `/views` w folderze `/client`. Będzie to miejsce wstawienia wszystkich szablonów. Aby trzymać porządek utworzymy również folder `/posts` w folderze `/views` przechowujący szablony mające związek z postami.
<% note do %>
### Znajdowanie plików
Meteor doskonale radzi sobie ze znajdowaniem plików. Nieważne gdzie wstawisz kod w folderz `/client`, Meteor go znajdzie i odpowiednio skompiluje. Oznacza to, że nigdy nie będziesz musiał wstawiał ścieżek 'include' do plików JavaScript czy CSS.
Oznacza to również, że mógłbyś równie dobrze wstawić wszystkie pliki w jeden folder, czy nawet cały kod w jeden plik. Ponieważ Meteor i tak skompiluje wszystko w jeden pojedyńczy skompresowany plik, chcielibyśmy raczej trzymać porządek i dobrze zorganizować strukturę plików.
<% end %>
W końcu jesteśmy gotowi utworzyć kolejny szablon. Utwórz plik `posts_list.html` w folderze `client/views/posts`:
~~~html
<template name="postsList">
<div class="posts">
{{#each posts}}
{{> postItem}}
{{/each}}
</div>
</template>
~~~
<%= caption "client/views/posts/posts_list.html" %>
Oraz `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/views/posts/post_item.html" %>
Zwróć uwagę na atrybut `name="postsList"` elementu szablonu. Jest to nazwa, którą Meteor wykorzysta do śledzenia miejsca, w który wstawić odpowiedni szablon.
Nadszedł czas wprowadzić system szablonów Meteora, [Handlebars](http://handlebarsjs.com). Handlebars jest po prostu HTML z dodatkiem trzech funkcji: *partials*, *expressions* (ang. wyrażeń) i *block helpers* (ang. helperów bloków kodu).
*Partials* używają składni `{{> nazwaSzablonu}}` i po prostu nakazują za zamienienie tego taga szablonem o tej samej nazwie (w naszym przypadku `postItem`).
*Expressions*, takie jak `{{title}}` mają dwojakie znaczenie: zwracają pole danego obiektu o nazwie title lub wartość zwracaną z helpera szablonu, który został zdefiniowany w bieżącym managerze szablonu (więcej o tym później).
Ostatecznie, *block helpers* to specjalne tagi, które kontrolują przebieg wykonania szablonu, np. `{{#each}}…{{/each}}` czy `{{#if}}…{{/if}}`.
<% note do %>
### Więcej szczegółów na temat Handlebars
Jeżeli chciałbyś się nauczyć więcej o Handlebars, przejdź na [oficjalny serwis Handlebars](http://handlebarsjs.com) lub przeczytaj [ten przydatny tutorial](http://javascriptissexy.com/handlebars-js-tutorial-learn-everything-about-handlebars-js-javascript-templating/)
<% end %>
Zaopatrzeni w tą wiedzę, możemy łatwo zrozumieć co dzieje się podczas wykonywania naszej aplikacji.
Najpierw, w szablonie `postsList` iterujemy po obiekcie `posts` za pomocą helpera bloku `{{#each}}…{{/each}}`. Następnie w każdej iteracji wstawiamy szablon `postItem`.
Skąd pochodzi obiekt `posts`? DObre pytanie. Jest to helper szablonu, który zdefiniujemy podczas zapoznawania się z managerami szablonu.
Szablon `postItem` jest w miarę prosty do opisania. Używa tylko trzech wyrażeń: `{{url}}` i `{{title}}` zwracają pola dokumentu, a `{{domain}}` woła helper szablonu.
Wiele razy wspomnieliśmy o "helperach szablonu" bez wyjaśniania jak działają. Aby do tego przejść, musimy najpierw wyjaśnić zasadę działania managera szablonu.
### Manager szablonu
DO tej pory mieliśmy styczność z Handlebars, które jest tak naprawdę HTML z kilkoma dodatkami w postaci tagów. W przeciwieństwie do innych języków takich jak PHP (czy nawet zwykłych stron HTML, które mogą zawierać JavaScript), Meteor oddziela szablony i ich logikę, a same szablony nie robią nic same z siebie.
Aby je ożywić, szablon potrzebuje **managera**. Możesz wyobrazić sobie analogię do szefa kuchni, który biorąc składniki potraw przygotowuje je przed podaniem kelnerowi (szablonowi), który go Tobie prezentuje.
Mówiąc inaczej, rola szablonów jest ograniczona do wyświetlania lub iterowania przez zmienne, manager wykonuje trudniejsze zadanie przez przypisanie wartości każdej zmiennej szablonu.
<% note do %>
### Manager?
Gdy zapytaliśmy programistów, jakie nazwy nadają managerom szablonu, połowa nazwała je "kontrolery", a druga połowa "te pliki, w których umieszczam kod JavaScript".
Manager nie jest tak naprawdę kontrolerem (przynajmniej w sensie kontrolera MVC) a termin "TFWIPMJSC" (przyp. tlum. ang. akronim od 'te pliki,...') nie dawał się łatwo zapamiętać, więc odrzuciliśmy obie propozycje.
Nadal potrzebowaliśmy nadać nazwę czemuś, nad czym pracujemy i wymyśliśmy nazwę "manager", która wcześniej nie miała swojego odpowiednika w innych frameworkach webowych.
<% end %>
Aby uprościć sytuację, zaadoptujemy konwencję nazywania managera tak samo, jak szablon, z wyjątkiem rozszerzenia **.js**. Stwórzmy zatem `posts_list.js` w folderze `/client/views/posts` i zacznijmy budowę pierwszego managera:
~~~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/views/posts/posts_list.js" %>
Jeżeli wszystko zostało wpisane poprawnie, powinieneś zobaczyć w przeglądarce:
<%= screenshot "3-1", "Pierwszy szablon zawierający dane statyczne" %>
<%= commit "3-1", "Dodany szablon listy postów i statyczne dane szablonu." %>
Osiągneliśmy tutaj dwie rzeczy. Po pierwsze ustawiliśmy dane początkowe prototypu aplikacji w talbice `postsData`. Dane te normalnie zostałyby pobrane z bazy danych, ale ponieważ jeszcze się tego nie nauczyliśmy (poczekaj do kolejnego rozdziału), "oszukujemy" przez wprowadzenie statycznych danych.
Po drugie, użyliśmy funkcję `Template.myTemplate.helpers()` Meteora, aby zdefiniować helper szablonu o nazwie `posts` który zwraca tablicę `postsData`.
Zdefiniowanie helpera `posts` oznacza, że jest on dostępny do użycia w obrębie szablonu:
~~~html
<template name="postsList">
<div class="posts">
{{#each posts}}
{{> postItem}}
{{/each}}
</div>
</template>
~~~
<%= caption "client/views/posts/posts_list.html" %>
Zatem nasz szablon będzie w stanie iterować po tablicy `postsData` i wysyłać każdy obiekt po kolei do szablonu `postItem`:
### Zawartość "this"
Stwórzmy manager `post_item.js`:
~~~js
Template.postItem.helpers({
domain: function() {
var a = document.createElement('a');
a.href = this.url;
return a.hostname;
}
});
~~~
<%= caption "client/views/posts/post_item.js" %>
<%= commit "3-2", "Ustawiony helper `domain` (domena) na `postItem`." %>
Tym razem wartością helpera `domain` nie jest tablica, ale funkcja anonimowa. Ten wzorzec jest jest częściej spotykany (i bardziej użyteczny) niż przedstawiony poprzednio przykład ze wstawieniem danych początkowych.
<%= screenshot "3-2", "Wyświetlenie domen dla każdego linku." %>
Helper `domain` ma URL jako paramter i zwraca jego domenę używając kilku sztuczek JavaScript. Ale skąd bierze się sam url?
Aby odpowiedzieć na to pytanie, musimy wrócić do szablonu `posts_list.html`. Block helper `{{#each}}` nie tylko iteruje po tablicy, are również **ustawia wartość `this` w środku bloku odpowiadającego iterowanemu obiektowi**.
Oznacza to, że pomiędzy tagami `{{#each}}`, każdy post po kolei jest równoznaczny z `this` i jest to zastosowane w każdym wstawioym managerze szablonu (`post_item.js`).
Rozumiemy teraz dlaczego `this.url()` zwraca URL bieżącego posta. Co więcej, jeżeli użyjemy `{{title}}` i `{{url}}` w środku szablonu `post_item.html`, Meteor rozpozna co oznacza `this.title` i `this.url` i zwróci poprawne wartości.
<% note do %>
### Sztuczki JavaScript
Mimo to, że nie jest to wyłącznie domena Meteora, przedstawimy szybko kilka "sztuczek JavaScript". Na początek stworzymy pusty link HTML (`a`) i zapiszemy go w pamięci.
Ustawimy następnie jego atrybut `href`, aby wskazywał na URL bieżącego posta (jak przed chwilą zobaczyliśmy, `this` jest bieżącym obiektem do którego szablon ma dostęp).
Na końcu wykorzystujemy fakt, że specjalne pole `hostname` elementu `a` można wykorzystać do zwrócenia nazwy domeny danego linka bez zwracania całego URL/
<% end %>
Jeżeli uważnie przeczytałeś bieżący rozdział i zastosowałeś się do instrukcji, powinieneś zobaczyć w przeglądarce listę postów. Ta lista to dane statyczne i nie wykorzystujemy jeszcze żadnych funkcji Meteora pozwalających na pracę z danymi zmieniającymi się w czasie rzeczywistym. W kolejnymi rozdziale pokażemy, jak to zmienić!
<% note do %>
### Przeładowanie kodu podczas pracy aplikacji (ang. Hot Code Reload)
Mogłeś zauważyć, że nie było konieczne odświeżenia okna przeglądarki po każdej zmianie pliku.
Dzieje się tak, ponieważ Meteor śledzi wszystkie pliki dostępne w folderze danego projektu i automatycznie odświeża przeglądarkę za każdym razem, gdy znajdzie zmianę w jakimkolwiek pliku.
Przeładowanie kodu jest bardzo sprytne, zachowuje również stan aplikacji między odświeżeniami strony!
<% end %>