Javascript代碼可以運行在兩種環境:客戶端(瀏覽器),和服務端(服務器上的Node.js容器)。 在API 參考中,我們會指出每個函數是否可以在客戶端,或是服務端,或是Anywhere(客戶端和服務端)被調用。
**模板**
在Meteor中,視圖定義在 模板 。模板就是包含動態數據的HTML代碼段。你可以通過javascript給模板插入數據,或是監聽模板事件。
**用HTML定義模板**
模板定義在.html文件中,可以放在項目任何位置,除了server,public,private文件夾
每個.html文件可以包含任意數量的頂級元素:`<head>,<body>`或是`<template>`。`<head>,<body>`標簽里的代碼會附加到HTML頁面中對應的標簽, `<tempalte>`標簽里的代碼可以用`{{> templateName}}`引入,如下面的例子所示。模板可以引入多次—模板的主要目的之一就是避免重復手寫相同的HTML。
~~~
<!-- add code to the <head> of the page -->
<head>
<title>兄弟會!</title>
</head>
<!-- add code to the <body> of the page -->
<body>
<h1>Hello!</h1>
{{> xiongdihui}}
</body>
<!-- define a template called xiongdihui -->
<template name="xiongdihui">
<p>Welcome to 兄弟會!</p>
</template>
~~~
{{ ... }}是Spacebars語法,Meteor使用Spacebars給HTML增加功能。如上所示,利用它你可以引入模板。 使用Spacebars,你可以顯示從 helpers 中獲取的數據。Helpers 用javascript來寫,既可以是簡單值,也可以是函數。
給nametag模板定義一個叫做name的helper(在javascript里):
~~~
Template.nametag.helpers({
name: "Ben Bitdiddle"
});
~~~
nametag 模板本身 (在HTML里):
~~~
<!-- In an HTML file, display the value of the helper -->
<template name="nametag">
<p>My name is {{name}}.</p>
</template>
~~~
Spacebars還有幾個方便使用的控制結構,可以使視圖更加動態:
{{#each data}} ... {{/each}} - 循環data里的每一項,每一項都會顯示一次#each塊里的HTML。
{{#if data}} ... {{else}} ... {{/if}} - 如果data為true,顯示第一個塊,反之,顯示第二個塊。
{{#with data}} ... {{/with}} - 設置內部HTML的數據上下文,然后顯示。
每一個嵌套的#each或#with塊都有自己的 數據上下文 ,數據上下文是一個對象,它的屬性在塊內部可以用作helper。例如:#with塊,它的數據上下文就是跟在它后面,}}之前的變量值。#each塊,循環到的元素會作為當前數據上下文。
例如,people helper 的值為:
~~~
Template.welcomePage.helpers({
people: [{name: "Bob"}, {name: "Frank"}, {name: "Alice"}]
});
~~~
然后你可以用一個<p>標簽列表顯示每一個人的姓名:
~~~
{{#each people}}
<p>{{name}}</p>
{{/each}}
~~~
或是用上面的"nametag"模板代替 <p>標簽:
~~~
{{#each people}}
{{> nametag}}
{{/each}}
~~~
記住:helper可以是簡答值,也可以是函數。例如,要顯示登錄用戶的用戶名,你可以定義一個叫做username的helper:
~~~
// in your JS file
Template.profilePage.helpers({
username: function () {
return Meteor.user() && Meteor.user().username;
}
});
~~~
現在,每次使用username helper的時候,都會調用上面的helper函數來確定用戶名:
~~~
<!-- in your HTML -->
<template name="profilePage">
<p>Profile page for {{username}}</p>
</template>
Helper可以接收參數。例如,
Template.post.helpers({
commentCount: function (numComments) {
if (numComments === 1) {
return "1 comment";
} else {
return numComments + " comments";
}
}
});
~~~
參數放在大括號里,helper名之后:
`<p>There are {{commentCount 3}}.</p>`
上面定義的helper都關聯到特定的模板,可以用Template.registerHelper定義所有模板都能用的helper。
關于Spacebars更詳細的文檔參見[README](http://meteor.fanxiao2.net)。后面的Session, Tracker,Collections, 和 Accounts小節會有如何給模板添加動態數據的討論。
傳給Template.myTemplate.events的事件map,用事件描述符作為key,事件處理函數作為value。事件處理函數接收兩個參數:事件對象和模板實例。事件處理函數中通過this獲取數據上下文。
假設有下面的模板:
~~~
<template name="example">
{{#with myHelper}}
<button class="my-button">My button</button>
<form>
<input type="text" name="myInput" />
<input type="submit" value="Submit Form" />
</form>
{{/with}}
</template>
~~~
調用 Template.example.events 給模板增加事件處理器:
~~~
Template.example.events({
"click .my-button": function (event, template) {
alert("My button was clicked!");
},
"submit form": function (event, template) {
var inputValue = event.target.myInput.value;
var helperValue = this;
alert(inputValue, helperValue);
}
});
~~~
key的前半部分是要捕獲的事件名稱。幾乎支持所有的DOM事件,常見的有:click, mousedown, mouseup, mouseenter, mouseleave, keydown, keyup, keypress, focus, blur, 和 change。
key的后半部分是CSS選擇器,用來指明要監聽的元素。幾乎支持所有JQuery支持的選擇器.
無論何時,選定元素上觸發了監聽的事件時,對應的事件處理函數就會被調用,參數為:DOM 事件對象和模板實例。詳細信息參見 [Meteor手冊](http://meteor.fanxiao2.net)
用這個方法注冊的函數會在Template.myTemplate模板的每個實例第一次插入到頁面的時候調用一次。
這個回調函數可以用來集成那些不適應Meteor自動視圖渲染機制,并且需要在每次HTML插入到頁面時進行初始化的第三方庫。 你可以在onCreated 和 onDestroyed回調中執行對象初始化或是清理工作。
例如,要使用HighlightJS庫高亮codeSample模板中所有`<pre>`元素,你可以傳遞如下回調函數給Template.codeSample.onRendered:
~~~
Template.codeSample.onRendered(function () {
hljs.highlightBlock(this.findAll('pre'));
});
~~~
在回調函數中,this指向一個template instance對象實例,`that is unique to this inclusion of the template and remains across re-renderings`.可以使用方法this.find 和 this.findAll來獲取模板渲染后的HTML DOM節點。