模板引擎
Express支援許多模板引擎,常用的有:
- haml 的實現Haml
- haml.js 接替者,同時也是Express的預設範本引擎Jade
- 嵌入JavaScript模板EJS
- 基於CoffeeScript的模板引擎CoffeeKup
- 的NodeJS版本jQuery模板引擎
視圖渲染(view randering)
視圖的檔案名稱預設需遵循“<name>.<engine>”的形式,這裡<engine>是要被載入的模組的名字。比如視圖layout.ejs就是在告訴視圖系統要require(‘ejs'),被載入的模組必須輸出exports.compile(str, options)方法,並要返回一個函數來遵守Express的模板介面約定。我們也可以使用app.register()來映射模板引擎到其它副檔名,從而實現更靈活的模板引擎行為,如此一來就可以實現“csser.html”可以被ejs引擎所渲染。
下面我們將用Jade引擎來渲染index.html,因為我們沒有設定layout:false,index.jade渲染後的內容將被作為body本地變數傳入layout.jade。
複製代碼 代碼如下:
<SPAN style="FONT-SIZE: 13px">app.get('/', function(req, res){
res.render('index.jade', { title: 'CSSer, 關注Web前端技術!' });
});
</SPAN>
新增的“view engine”設定可以指定預設範本引擎,如果我們想使用jade可以這樣設定:
複製代碼 代碼如下:
<SPAN style="FONT-SIZE: 13px">app.set('view engine', 'jade');
</SPAN>
於是我們就可以通過下面的方式:
複製代碼 代碼如下:<SPAN style="FONT-SIZE: 13px">res.render('index');
</SPAN>
代替如下方式:
複製代碼 代碼如下:<SPAN style="FONT-SIZE: 13px">res.render('index.jade');
</SPAN>
當“view engine”設定後,模板的副檔名就成了可選項,同時我們還可以混合匹配多模板引擎:
複製代碼 代碼如下:<SPAN style="FONT-SIZE: 13px">res.render('another-page.ejs');
</SPAN>
Express同時提供了視圖選項設定,這些設定會在每次視圖渲染後應用,比如你並不經常使用layouts,就可以這樣設定:
複製代碼 代碼如下:<SPAN style="FONT-SIZE: 13px">app.set('view options', {
layout: false
});
</SPAN>
如果需要,這些設定可以在後續的res.render()調用中被覆蓋:
複製代碼 代碼如下:<SPAN style="FONT-SIZE: 13px">res.render('csser-view.ejs', { layout: true });
</SPAN>
可以通過指定一個路徑的方式來實現用自己的layout來代替系統預設的,比如如果我們將“view engine”設定為jade並且自訂了一個名為“./views/mylayout.jade”的layout,我們可以這樣使用它:
複製代碼 代碼如下:<SPAN style="FONT-SIZE: 13px">res.render('page', { layout: 'mylayout' });
</SPAN>
否則必須指定副檔名:
複製代碼 代碼如下:<SPAN style="FONT-SIZE: 13px">res.render('page', { layout: 'mylayout.jade' });
</SPAN>
這些路徑也可以是絕對路徑:
複製代碼 代碼如下:<SPAN style="FONT-SIZE: 13px">res.render('page', { layout: __dirname + '/http://www.jb51.net/mylayout.jade' });
</SPAN>
這方面較好的例子就是自訂ejs模板的開始和關閉的標記:
複製代碼 代碼如下:<SPAN style="FONT-SIZE: 13px">app.set('view options', {
open: '{{',
close: '}}'
});
</SPAN>
局部視圖(View Partials)
Express視圖系統原生支援局部和集合視圖,這稱作微型視圖,主要用於渲染一個文檔片段。比如與其在視圖中迴圈顯示評論,不如使用局部集合(partial collection):
複製代碼 代碼如下:<SPAN style="FONT-SIZE: 13px">partial('comment', { collection: comments });
</SPAN>
如果不需要其它選項或本地變數,我們可以省略對象而簡單的傳入評論數組,這和上面的樣本是一樣的:
複製代碼 代碼如下:<SPAN style="FONT-SIZE: 13px">partial('comment', comments);
</SPAN>
當使用局部集合時,支援一些“魔術”本地變數:
- firstInCollection 當為第一個對象時該值為true
- indexInCollection 集合中對象的索引值
- lastInCollection 當為最後一個對象時為true
- collectionLength 集合的長度
Local variables passed (or generated) take precedence, however locals passed to the parent view are available in the child view as well. So for example if we were to render a blog post with partial(‘blog/post', post) it would generate the post local, but the view calling this function had the local user, it would be available to the blog/post view as well.
傳入(或產生)的本地變數優先,但傳入父視圖的本地變數在子視圖仍有效。因此如果我們用partial(‘blog/post', post)來渲染部落格日誌時,將產生post的本地變數,但調用本函數的視圖擁有本機使用者,它在blog/post視圖依然有效。(一回註:這段翻譯感覺有問題,請高人指點)。
效能提示:當使用局部集合渲染100長度的數組就意味著需要渲染100次視圖,對於簡單的集合你可以將迴圈內聯,而不要使用局部集合,這樣可以減少系統開銷。
視圖尋找(View Lookup)
視圖尋找是相對於父視圖進行的,比如我們有一個名為“views/user/list.jade”的整頁模式,如果在該視圖中調用 partial(‘edit'),視圖系統將會嘗試尋找並載入“views/user/edit.jade”,而partial(‘.. /messages')將載入“views/messages.jade”。
視圖系統還支援索引模板,這樣你就可以使用一個同名的目錄。比如,在一個路由中我們執行res.render(‘users'),這將指向“views/users.jade”或者“views/users/index.jade”。
當使用上面的索引檢視表時,我們可以通過partial(‘users')從同名目錄下引用“views/users/index.jade”,同時視圖系統會嘗試“../users/index”,這能減少我們調用partial(‘index')的需要。