Block helper可以讓你自定義迭代器和其他可以傳入新的上下文的功能
基本塊
Block helper的定義方法是:在一個mustache中,以#
開頭,後面跟着helper的名稱,然後對應的在一個mustache中以/
開頭,加上相同的名稱作爲這個塊的結尾。
形如:
{{#hello}}
{{item}}
{{/hello}}
在helper中,function接收一個hash參數options,而options有個fn方法,該方法可接收一個context參數來改變block中的上下文,返回一個類似於編譯後的Handlebars模板,明確地說,就是一個字符串。
Handlebars.registerHelper('hello', function(options){
return options.fn(this);
});
在上面的代碼中,我們給options.fn傳入了一個新的上下文,這個新的context是this,就是代表當前的上下文,因此,如果當前的上下文是:
{
title: 'This is the title.',
body: 'body',
item: 'item'
}
那麼block中的item標識符最終返回字符串'item'
注:以這種方式定義的helper,在模板中,可以使用path,如上面的{{item}}
可以寫成{{./item}}
with helper(內置)
with helper會把傳入的context直接調用,實現如下
Handlebars.registerHelper('with', function(context, options) {
return options.fn(context);
});
當處理json的時候用with比較方便
<div class="entry">
<h1>{{title}}</h1>
{{#with story}}
<div class="intro">{{{intro}}}</div>
<div class="body">{{{body}}}</div>
{{/with}}
</div>
context:
{
title: "First Post",
story: {
intro: "Before the jump",
body: "After the jump"
}
}
簡單迭代器
先來看一下內置的each helper是怎麼實現的
<div class="comments">
{{#each comments}}
<div class="comment">
<h2>{{subject}}</h2>
{{{body}}}
</div>
{{/each}}
</div>
helper:
Handlebars.registerHelper('each', function(context, options) {
var ret = "";
for(var i=0, j=context.length; i<j; i++) {
ret = ret + options.fn(context[i]);
}
return ret;
});
其實就是在helper中遍歷了一次context。明白了這一點,我們就可以對其進行改造,實現自定義的迭代器了。如:
{{#list nav}}
<a href="{{url}}">{{title}}</a>
{{/list}}
context:
{
nav: [
{ url: "http://www.yehudakatz.com", title: "Katz Got Your Tongue" },
{ url: "http://www.sproutcore.com/block", title: "SproutCore Blog" },
]
}
helper:
Handlebars.registerHelper('list', function(context, options) {
var ret = "<ul>";
for(var i=0, j=context.length; i<j; i++) {
ret = ret + "<li>" + options.fn(context[i]) + "</li>";
}
return ret + "</ul>";
});
條件表達式
Handlebars中內置的if只能判斷true/false,具體實現如下:
{{#if isActive}}
<img src="star.gif" alt="Active">
{{else}}
<img src="cry.gif" alt="Inactive">
{{/if}}
helper:
Handlebars.registerHelper('if', function(conditional, options) {
if(conditional) {
return options.fn(this);
} else {
return options.inverse(this);
}
});
其中,options.inverse
用來處理block中的else語句,對此,我們也可以實現自定義的條件helper來增強條件語句的功能
Handlebars.registerHelper('equal' function(param1, param2, options) {
if(param1 == param2) {
return options.fn(this);
} else {
return options.inverse(this);
}
});
{{#equal 'hello' 'world'}}
<p>==</p>
{{else}}
<p>!=</p>
{{/equal}}
以上示例展示了判斷兩個變量相等或不等時執行的操作。
此外,Handlebars支持鏈式的條件語句,如
{{#if isActive}}
<img src="star.gif" alt="Active">
{{else if isInactive}}
<img src="cry.gif" alt="Inactive">
{{/if}}
hash參數
hash arguments在之前的文章有提到過,就是將一些鍵值對序列作爲helper回調函數最後一個參數的值,通過options.hash
來訪問。
{{#list nav id="nav-bar" class="top"}}
<a href="{{url}}">{{title}}</a>
{{/list}}
Handlebars.registerHelper('list' function(context, options) {
var attrs = Em.keys(options.hash).map(function(key) {
return key + '="' + options.hash[key] + '"';
}).join(" ");
return "<ul " + attrs + ">" + context.map(function(item) {
return "<li>" + options.fn(item) + "</li>";
}).join("\n") + "</ul>";
});
塊參數
Handlebars 3.0的新特性。
{{#each users as |user userId|}}
Id: {{userId}} Name: {{user.name}}
{{/each}}
這邊user
會取當前context的值,而userId
會取當前遍歷context的索引值。
有點類似於JavaScript裏的Array.map
raw helper
之前也提到過,用來轉義的
{{{{raw-helper}}}}
{{bar}}
{{{{/raw-helper}}}}
helper:
Handlebars.registerHelper('raw-helper', function(options) {
return options.fn();
});
輸出:
{{bar}}