helper大概能夠分爲兩類,一類是用於格式化輸出數據,使用起來像這樣:{{formatDate date}},官方沒有給起名字,我姑且叫作簡單helper好了。另外一類叫塊級helper,塊級helper有本身的做用域,能夠拿到上下文數據,並能夠定義渲染的內容,能夠發揮的做用就比較大了。經過這兩類helper,handlebars由一個弱邏輯的模板能夠擴展出很強大的功能。經過registerHelper方法,咱們即可以註冊一個helper。下面先看一下簡單helper。less
簡單helper
簡單helper主要用來對數據進行格式化,例如咱們常常會格式化日期、數字、金額等等。看一個例子就明白了,此處我寫一個把數字進行千分位分割的helper,所謂千分位分割就是把123456789這樣的值格式化爲123,456,789.代碼以下:函數
Handlebars.registerHelper('formatnumber', function(num, options){ num = num + ''; return num.replace(/(?=(?!^)(?:\d{3})+(?:\.|$))(\d{3}(\.\d+$)?)/g,',$1'); });
而後就能夠在模板中使用:post
{{formatnumber num}}
registerHelper的第一個參數是helper的名稱,我這裏把它叫作formatnumber,第二個參數是一個函數,該函數傳入的第一個參數就是咱們在使用helper時候的值,如上面的num,最後,函數return的內容就是咱們模板中輸出的內容。此外還會傳入第二個參數options,options是一個對象,包含上下文相關的一些信息,不過在簡單helper中用不到,咱們會下面在塊級helper中詳細說說。性能
一個簡單helper的定義就是如此簡單,真如其名~測試
塊級helper
塊級helper的能力就強大不少,能夠實現一些本身想要的迭代器,或者加強判斷語句等。主要依賴的就是這個options參數。下面經過一個例子來講明一下。this
handlebars的if語句只能進行true/false判斷,若是咱們想判斷一個數字是不是偶數,我這麼寫是不能夠的:{{#if num%2 == 0}},if不支持表達式,也不支持==這樣的操做符。因此要想在模板中判斷偶數,咱們須要定義一個helper。代碼以下:spa
//判斷是不是偶數 Handlebars.registerHelper('if_even', function(value, options) { console.log('value:', value); // value: 2 console.log('this:', this); // this: Object {num: 2} console.log('fn(this):', options.fn(this)); // fn(this): 2是偶數 if((value % 2) == 0) { return options.fn(this); } else { return options.inverse(this); } });
而後咱們造一個數據,寫在模板中來看看:3d
var data3 = { num : 2 }
模板中:code
{{#if_even num}} {{this.num}}是偶數 {{else}} {{this.num}}是奇數 {{/if_even}}
獲得的結果是輸出「2是偶數」。經過在代碼中log出的數據,能夠看到用this能夠取到當前的上下文主體,此處就是咱們的定義好的數據對象了。另一個比較重要的就是options.fn方法,此方法能夠將你傳入的上下文主體編譯到模板,返回編譯後的結果,在helper中,咱們把this傳了進去,因而在模板中也能夠引用到它。最終options.fn返回編譯後的結果:2是偶數。其實你也能夠爲options.fn傳入其餘的上下文對象,好比你要寫一個迭代器,能夠把數組的元素依次傳入。
此處咱們還看到了另外一個方法,options.inverse,它是取相反的意思,對應了咱們模板中的{{else}}標籤,它會編譯{{else}}中的的內容並返回結果,若是咱們的helper中須要帶else邏輯,用它就能夠了。
塊級helper在用的時候開頭要加"#",而且要有結束符,就是上面的{{/if_even}}
接收多個參數的helper
自定義helper能夠傳入多個參數,只要依次寫在registerHelper的函數中就能夠了,看下面一個例子。
因爲handlebars內置的if語句太弱,有時候咱們須要判斷像==、!=、>、<這樣的邏輯,就必須本身寫定義helper了。這樣的helper須要傳入左右操做數還有操做符,參數不僅一個。下面這個compare是從別的地方抄來的,也是我在項目中用的最多的:
使用的時候是這樣:
{{#compare people.name '==' 'peter'}} 他的名字是peter {{else}} 他的名字不是peter {{/compare}}
能夠看到在模板中傳入的參數依次對應helper定義中的left、operator、options。同時定義中也是用了options.inverse,用來處理else的邏輯。
爲helper傳入hash參數
在模板中使用helper的時候,咱們還能夠爲helper傳入一些變量參數,叫作hash參數,在helper中能夠經過options.hash拿到這些參數進行處理。這樣helper的靈活性和可複用性就大大加強了。咱們仍是舉例來講明。
定義一個名爲list的helper,它的做用是循環輸出數據,並把數據包裹在ul>li標籤中。同時爲了給元素增長不一樣的class,我把class名稱做爲hash來傳入。helper代碼以下:
Handlebars.registerHelper('list', function(items, options) { var out = '<ul>'; for(var i=0, l=items.length; i<l; i++) { var item = options.fn(items[i]); out = out + '<li class="+options.hash.class+">' + item + '</li>'; } return out + '</ul>'; });
在模板中,我使用了兩次list,並傳入不一樣的hash值:
{{#list people class="green"}}{{firstName}}-----{{lastName}}{{/list}} {{#list people class="red"}}{{firstName}}-----{{lastName}}{{/list}}
定義如下數據作測試:
var data = { people: [ {firstName: "Yehuda", lastName: "Katz"}, {firstName: "Carl", lastName: "Lerche"}, {firstName: "Alan", lastName: "Johnson"} ] }
最終頁面上生成的節點以下所示:
這樣咱們就重用了同一個helper,完成了更加靈活的任務。看到這裏,是否是以爲helper很強大了呢,利用上面這些特性,咱們能夠寫出很是豐富的功能了,足以知足開發需求。
其餘
另外還有兩點的小知識,補充在此處:
1. helper的銷燬
調用Handlebars.unregisterHelper('list')便可銷燬一個helper
2. 一次註冊多個helper
andlebars.registerHelper({ foo: function() {}, bar: function() {} });
handlebars做爲一個弱邏輯的靜態模板引擎,自己簡單好用,沒有太多冗餘的東西,同時還提供了強大的擴展性,這也是我喜歡它的緣由。但願經過本篇文章能讓你更多的瞭解handlebars的helper,開始喜歡上它。