Handlebars學習之——塊表達式

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}}

參考

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章