-
Notifications
You must be signed in to change notification settings - Fork 12
/
03-templates.md.erb
231 lines (157 loc) · 11 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: Templates
slug: templates
date: 0003/01/01
number: 3
contents: Utilizzare il linguaggio di templating di Meteor, Spacebars.|Creare i tuoi primi 3 template.|Come funzionano i manager in Meteor.|Ottenere un prototipo base utilizzando dati statici.
paragraphs: 46
---
Per rendere semplice l'apprendimento dello sviluppo in Meteor, adotteremo un approccio dall'esterno. In altre parole realizzeremo prima una semplice struttura in HTML/JavaScript e la integreremo con le funzionalità dell'applicazione solo in un secondo momento.
Ciò significa che in questo capitolo ci preoccuperemo solamente di ciò che accade all'interno della cartella `/client`.
Creiamo un nuovo file chiamato `main.html` all'interno della cartella `/client` e inseriamoci il seguente codice:
~~~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" %>
Questo sarà il template principale della nostra applicazione. Come potete notare si tratta di semplice HTML ad eccezione del tag `{{> postsList}}`, che rappresenta il punto di inserimento del template `postsList` che vedremo a breve. Per ora creiamo altri 2 template.
### Template in Meteor
Alla base, un sito di notizie social è composto di post organizzati in liste, e questo è esattamente il modo in cui andremo ad organizzare i nostri template.
Creiamo un cartella `/views` all'interno della cartella `/client`. In questa cartella andremo a posizionare tutti i nostri template e per mantenere la struttura ordinata creiamo una cartella `/posts` all'interno di `/views` solo per i template relativi ai post.
<% note do %>
### Come trovare i file
Meteor è grandioso a trovare i file. Non importa dove e come mettete il codice all'interno della cartella `/client`, Meteor lo troverà e lo compilerà correttamente. Questo significa che non dovrete mai inserire manualmente i riferimenti ai file JavaScript e CSS.
Questo significa anche che potete inserire tutti i vostri file nella stessa cartella, o anche tutto il vostro codice in un solo file, ma visto che Meteor compilerà tutto in un singolo file minificato, è meglio tenere tutto ben organizzato in una struttura file ordinata.
<% end %>
Creiamo finalmente il nostro secondo template. Dentro `client/views/posts`, creiamo `posts_list.html`:
~~~html
<template name="postsList">
<div class="posts">
{{#each posts}}
{{> postItem}}
{{/each}}
</div>
</template>
~~~
<%= caption "client/views/posts/posts_list.html" %>
E `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" %>
Notate l'attributo `name="postsList"` dell'elemento template. Questo è il nome che viene utilizzato da Meteor per tenere traccia di dove vanno inseriti i vari template.
È il momento di introdurre il sistema di template di Meteor, Spacebars. Spacebars è semplice HTML, con l'aggiunta di tre particolarità: *parziali*, *espressioni* e *blocchi di controllo*.
I *parziali* usano la sintassi `{{> templateName}}`, e dicono semplicemente a Meteor di sostituire il parziale con il template con lo stesso nome (nel nostro caso `postItem`).
Le *espressioni* come `{{title}}` possono richiamare sia una proprietà dell'oggetto attuale, o il valore restituito da un helper del template come definito nel manager del template attuale (parleremo meglio più avanti di questo).
Infine, i *blocchi di controllo* sono tag speciali che controllano il flusso del template come `{{#each}}…{{/each}}` o `{{#if}}…{{/if}}`.
<% note do %>
### Più informazioni
Potete far riferimento alla [documentazione di Spacebars](https://github.com/meteor/meteor/blob/devel/packages/spacebars/README.md) se volete imparare di più su Spacebars.
<% end %>
Armati di queste nuove conoscenze, possiamo facilmente capire cosa sta succedendo.
Come prima cosa nel template `postsList`, stiamo iterando su un oggetto `posts` grazie al blocco di controllo `{{#each}}…{{/each}}`. Successivamente, per ogni iterazione, includiamo il template `postItem`.
Da dove arriva questo oggetto `posts`? Buona domanda. Si tratta di un helper di template che definiremo più avanti quando di occuperemo dei manager di template.
Il template `postItem` è abbastanza lineare. Usa solo tre espressioni: `{{url}}` e `{{title}}` ritornano le proprietà del documento, mentre `{{domain}}` chiama un helper del template.
Abbiamo nominato molte volte gli "helper del template" in questo capitolo senza in realtà spiegare come funzionano. Prima di poter riparare a questa mancanza dobbiamo parlare dei manager.
### Manager dei Template
Fino ad ora abbiamo lavorato con Spacebars, che non è altro che puro HTML con l'aggiunta di qualche tag speciale. Contrariamente ad altri linguaggi come PHP (o anche normali pagine HTML, che possono includere JavaScript), Meteor tiene i template e la logica separati, e i template da soli non sono sufficienti.
Per prendere vita, un template ha bisogno di un **manager**. Potete immaginare un manager come uno chef che prende ingredienti grezzi (i vostri dati) e li prepara, prima di consegnare il piatto pronto al cameriere (il template) che ve lo presenta una volta pronto.
In altre parole, mentre il ruolo del template è limitato al mostrare o iterare su delle variabili, il manager è colui che si occupa del lavoro duro, assegnando un valore ad ogni variabile.
<% note do %>
### Manager?
Quando abbiamo chiesto ad altri sviluppatori Meteor come avrebbero chiamato i manager di template, metà ha risposto "controller", e metà "quei file dove metto il mio codice JavaScript".
I manager non sono esattamente controller (per lo meno non nel senso di controller MVC) e "QFDMIMCJ" non è certo un acronimo accattivante, così abbiamo accantonato entrambe le proposte.
Dato che avevamo comunque bisogno di indicare in modo comprensibile ciò di cui stavamo parlando, abbiamo optato per chiamarli "manager", termine che non ha nessun particolare significato all'interno di altri framework web e quindi più comodo per rappresentare qualcosa di nuovo.
<% end %>
Per mantenere una certa semplicità, useremo la convenzione di nominare i manager in base al template, con la differenza di avere l'estensione **.js**. Creiamo quindi `posts_list.js` all'interno di `/client/views/posts` e iniziamo a scrivere il nostro primo manager:
~~~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" %>
Se avete fatto correttamente, dovreste vedere qualcosa di simile nel vostro browser:
<%= screenshot "3-1", "Il nostro primo template con dati statici" %>
<%= commit "3-1", "Aggiunto template di base della lista dei post e alcuni dati statici." %>
In questo codice stiamo facendo due cose. Come prima cosa stiamo inserendo dati di esempio come schema di base nell'array `postsData`. Questi dati normalmente verrebbero dal database ma dal momento che non abbiamo ancora visto come fare (lo faremo nel prossimo capitolo) stiamo "bluffando" utilizzando dei dati statici.
In secondo luogo, stiamo utilizzando la funzione di Meteor `Template.myTemplate.helpers()` per definire un helper del template chiamato `posts` che semplicemente ci restituisce l'array `postsData`.
Definendo l'helper `posts`, lo rendiamo disponibile al nostro template:
~~~html
<template name="postsList">
<div class="posts">
{{#each posts}}
{{> postItem}}
{{/each}}
</div>
</template>
~~~
<%= caption "client/views/posts/posts_list.html" %>
In questo modo, il template potrà iterare sull'array `postsData` ed inviare ogni oggetto contenuto al suo interno al template `postItem`.
### Il valore di "this"
Creiamo ora il 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", "Setup a `domain` helper on the `postItem`." %>
Questa volta il valore del nostro helper `domain` non è un array, ma una funzione anonima. Questo pattern è molto più diffuso (e utile) se paragonato al nostro precedente esempio con semplici dati statici.
<%= screenshot "3-2", "Visualizzazione del dominio di ogni link." %>
L'helper `domain` riceve un URL e ne restituisce il dominio tramite un po' di magia in JavaScript. Ma da dove proviene questo URL?
Per rispondere a questa domanda dobbiamo tornare al nostro template `posts_list.html`. Il blocco di controllo `{{#each}}` non solo itera sul nostro array ma **definisce il valore di `this` sull'oggetto iterato all'interno del blocco**.
Questo significa che all'interno dei tag `{{#each}}`, ogni post è assegnato al valore di `this` ad ogni iterazione, e si estende automaticamente all'interno del manager del template incluso (`post_item.js`).
Ora possiamo capire perché `this.url` restituisce l'URL dell'attuale post. E inoltre, se usiamo `{{title}}` e `{{url}}` all'interno del nostro template `post_item.html`, Meteor sa che si tratta in realtà di `this.title` e `this.url` e ci restituisce i valori corretti.
<% note do %>
### JavaScript Magic
Sebbene non sia proprio di Meteor, di seguito trovate una veloce spiegazione del precedente pizzico di "magia JavaScript". Come prima cosa, creiamo un elemento HTML vuoto, (`a`), e lo teniamo in memoria.
Definiamo poi il valore del suo attributo `href` tramite il valore dell'URL del post attuale (come abbiamo appena visto, in un helper `this` è l'oggetto sul quale stiamo al momento operando).
Infine sfruttiamo la proprietà speciale dell'elemento `a`, `hostname`, per recuperare il nome del dominio del link senza il resto dell'URL.
<% end %>
Se avete seguito i passaggi correttamente, dovreste vedere una lista di post nel vostro browser. Questa lista è formata solo da dati statici, perciò non si avvale ancora delle caratteristiche in tempo reale di Meteor. Vi mostreremo come modificare questa 'mancanza' nel prossimo capitolo!
<% note do %>
### Ricaricamento del codice
Vi sarete forse accorti che non dovete nemmeno ricaricare il vostro browser ogni volta che modificate un file.
Questo avviene perché Meteor traccia tutti i file all'interno della cartella del progetto e ricarica automaticamente il browser ogni volta che si accorge di una modifica in uno qualsiasi di essi.
Il ricaricamento del codice di Meteor è piuttosto intelligente, infatti mantiene lo stato della vostra applicazione anche nel mezzo di due ricaricamenti!
<% end %>