使用Handlebars,你能夠輕鬆建立語義化模板,Mustache模板和Handlebars是兼容的,因此你能夠將Mustache導入Handlebars以使用 Handlebars 強大的功能。javascript
開始
Handlebars模板看起來和HTML同樣,只是嵌入了 handlebars 表達式html
- <div class="entry">
- <h1>{{title}}</h1>
- <div class="body">
- {{body}}
- </div>
- </div>
handlebars表達式以{{
開頭,中間寫一些內容,以}}
結尾。java
你可使用<script>
標籤引入handlebars模板:express
- <script id="entry-template" type="text/x-handlebars-template">
- template content
- </script>
在javascript中使用Handlebars.compile
編譯模板:瀏覽器
- var source = $("#entry-template").html();
- var template = Handlebars.compile(source);
你也能夠預編譯你的模板,而後只需引入更小的運行時庫(handlebars.runtime.js),避免在瀏覽器中編譯,提升性能,這在移動設備中顯得更重要。安全
傳入數據上下文(context),handlebars會執行並生成HTML:less
- var context = {title: "My New Post", body: "This is my first post!"}
- var html = template(context);
獲得的結果是:函數
- <div class="entry">
- <h1>My New Post</h1>
- <div class="body">
- This is my first post!
- </div>
- </div>
HTML編碼
在handlebars裏,{{expression}}
會返回一個通過編碼的HTML,若是你不但願被編碼,可使用{{{
post
- <div class="entry">
- <h1>{{title}}</h1>
- <div class="body">
- {{{body}}}
- </div>
- </div>
使用這樣的數據上下文:性能
- {
- title: "All about <p> Tags",
- body: "<p>This is a post about <p> tags</p>"
- }
結果是:
- <div class="entry">
- <h1>All About <p> Tags</h1>
- <div class="body">
- <p>This is a post about <p> tags</p>
- </div>
- </div>
handlebars不會編碼Handlebars.SafeString
。若是你自定義一個helper,返回一段HTML代碼,你須要返回new Handlebars.SafeString(result)
。此時,你須要手動對內容進行編碼:
- Handlebars.registerHelper('link', function(text, url) {
- text = Handlebars.Utils.escapeExpression(text);
- url = Handlebars.Utils.escapeExpression(url);
-
- var result = '<a href="' + url + '">' + text + '</a>';
-
- return new Handlebars.SafeString(result);
- });
這裏將會對傳入的參數進行編碼,返回值是「安全的」,因此就算你不使用{{{
,handlebars也不會再次編碼了。
塊表達式
塊表達式容許你定義helper,用不一樣的數據上下文(context)調用一段模板。下面咱們定義一個生成列表的helper:
- {{#list people}}{{firstName}} {{lastName}}{{/list}}
若是咱們的數據是這樣的:
- {
- people: [
- {firstName: "Yehuda", lastName: "Katz"},
- {firstName: "Carl", lastName: "Lerche"},
- {firstName: "Alan", lastName: "Johnson"}
- ]
- }
咱們建立一個叫list
的helper來生成列表,helper接受people
做爲第一個參數,一個option對象(hash)做爲第二個參數。option包含一個屬性fn
,他能夠調用一個context就像普通模板同樣。
- Handlebars.registerHelper('list', function(items, options) {
- var out = "<ul>";
-
- for(var i=0, l=items.length; i<l; i++) {
- out = out + "<li>" + options.fn(items[i]) + "</li>";
- }
-
- return out + "</ul>";
- });
執行後,獲得:
- <ul>
- <li>Yehuda Katz</li>
- <li>Carl Lerche</li>
- <li>Alan Johnson</li>
- </ul>
塊表達式有不少特性,例如,能夠建立一個else
塊(內置的if helper就有else塊)。另外,若是options.fn(context)
對內容編碼過了,handlebars就不會helper內容進行編碼了,不然就編碼兩次了。
更多內容:塊表達式
Handlebars 路徑
Handlebars支持簡單的路徑
- <p>{{name}}</p>
也支持嵌套路徑,能夠查找下一級的屬性
- <div class="entry">
- <h1>{{title}}</h1>
- <h2>By {{author.name}}</h2>
-
- <div class="body">
- {{body}}
- </div>
- </div>
此模板使用下面的數據:
- var context = {
- title: "My First Blog Post!",
- author: {
- id: 47,
- name: "Yehuda Katz"
- },
- body: "My first post. Wheeeee!"
- };
嵌套路徑一樣支持../,
- <h1>Comments</h1>
-
- <div id="comments">
- {{#each comments}}
- <h2><a href="/posts/{{../permalink}}#{{id}}">{{title}}</a></h2>
- <div>{{body}}</div>
- {{/each}}
- </div>
儘管連接在打印出的時候,是以comments爲上下文的,可是它能夠訪問到上一級的上下文(context)找到permalink。
../引用上一級的做用域,直接看一下上面模板對應的數據就明白了
- var data = {
- permalink:'http://keenwon.com',
- comments: [
- {id:1,title:'連接1',body:'連接1'},
- {id:2,title:'連接2',body:'連接2'}
- ]
- };
Handlebars能夠經過this
引用解決helpers和數據命名衝突的問題。
- <p>{{./name}} or {{this/name}} or {{this.name}}</p>
模板註釋 {{! }}
or {{!-- --}}
你能夠在 handlebars 里加註釋:
- <div class="entry">
- {{! only output this author names if an author exists }}
- {{#if author}}
- <h1>{{firstName}} {{lastName}}</h1>
- {{/if}}
- </div>
註釋不會出如今輸出結果裏,若是想要顯示出來,可使用html的註釋(會被執行,而後以註釋的形式顯示,因此若是html註釋內有錯,仍是會報錯)
- <div class="entry">
- {{! 這個註釋不會顯示在輸出結果中 }}
- <!-- 會顯示 -->
- </div>
全部註釋必須包含結束標籤}}
,多行註釋可使用{{!-- --}}
Helpers
Handlebars Helpers能夠讀取到模板中的任何數據上下文,你可使用Handlebars.registerHelper
註冊一個helpers。
- <div class="post">
- <h1>By {{fullName author}}</h1>
- <div class="body">{{body}}</div>
-
- <h1>Comments</h1>
-
- {{#each comments}}
- <h2>By {{fullName author}}</h2>
- <div class="body">{{body}}</div>
- {{/each}}
- </div>
而後使用以下的數據上下文和Helpers:
- var context = {
- author: {firstName: "Alan", lastName: "Johnson"},
- body: "I Love Handlebars",
- comments: [{
- author: {firstName: "Yehuda", lastName: "Katz"},
- body: "Me too!"
- }]
- };
-
- Handlebars.registerHelper('fullName', function(person) {
- return person.firstName + " " + person.lastName;
- });
結果是:
- <div class="post">
- <h1>By Alan Johnson</h1>
- <div class="body">I Love Handlebars</div>
-
- <h1>Comments</h1>
-
- <h2>By Yehuda Katz</h2>
- <div class="body">Me Too!</div>
- </div>
使用this
能夠訪問到當前的上下文
- <ul>
- {{#each items}}
- <li>{{agree_button}}</li>
- {{/each}}
- </ul>
使用以下的Helpers和數據上下文
- var context = {
- items: [
- {name: "Handlebars", emotion: "love"},
- {name: "Mustache", emotion: "enjoy"},
- {name: "Ember", emotion: "want to learn"}
- ]
- };
-
- Handlebars.registerHelper('agree_button', function() {
- return new Handlebars.SafeString(
- "<button>I agree. I " + this.emotion + " " + this.name + "</button>"
- );
- });
結果是:
- <ul>
- <li><button>I agree. I love Handlebars</button></li>
- <li><button>I agree. I enjoy Mustache</button></li>
- <li><button>I agree. I want to learn Ember</button></li>
- </ul>
若是你的helpers返回一個html片斷,不想被編碼。必須new一個Handlebars.SafeString
返回出來。
內置的Helpers
The with
Block Helper
一般,Handlebars會將數據上下文傳入編譯方法:
- var source = "<p>{{lastName}}, {{firstName}}</p>";
- var template = Handlebars.compile(source);
- template({firstName: "Alan", lastName: "Johnson"});
結果:
- <p>Johnson, Alan</p>
使用with
能夠改變當前的上下文
- <div class="entry">
- <h1>{{title}}</h1>
-
- {{#with author}}
- <h2>By {{firstName}} {{lastName}}</h2>
- {{/with}}
- </div>
數據上下文以下:
- {
- title: "My first post!",
- author: {
- firstName: "Charles",
- lastName: "Jolley"
- }
- }
結果:
- <div class="entry">
- <h1>My first post!</h1>
-
- <h2>By Charles Jolley</h2>
- </div>
The each
block helper
你可使用內置的each
helper生成列表,可使用this
訪問當前項。
- <ul class="people_list">
- {{#each people}}
- <li>{{this}}</li>
- {{/each}}
- </ul>
數據上下文以下:
- {
- people: [
- "Yehuda Katz",
- "Alan Johnson",
- "Charles Jolley"
- ]
- }
結果:
- <ul class="people_list">
- <li>Yehuda Katz</li>
- <li>Alan Johnson</li>
- <li>Charles Jolley</li>
- </ul>
你能夠在任何上下文裏,使用this
引用當前的上下文
另外,還可使用{{else}}
塊,當列表內容爲空的時候會顯示{{else}}
的內容
- {{#each paragraphs}}
- <p>{{this}}</p>
- {{else}}
- <p class="empty">暫無內容</p>
- {{/each}}
在each
中循環每一項的時候,可使用{{@index}}
獲取當前的序號。
- {{#each array}}
- {{@index}}: {{this}}
- {{/each}}
對於object,可使用{{key}}
獲取當前的key。
- {{#each object}}
- {{@key}}: {{this}}
- {{/each}}
在迭代的過程當中,可使用@first
和@last
判斷當前的第一步和最後一步,對於object,只有@first
可用。
The if
block helper
可使用if
helper有條件的渲染block,若是是false
, undefined
, null
, ""
或者 []
(a 「falsy」 value),Handlebars不會渲染此block.
- <div class="entry">
- {{#if author}}
- <h1>{{firstName}} {{lastName}}</h1>
- {{/if}}
- </div>
若是使用的是空的數據上下文(例如{}
),author會返回undefined
,結果是:
- <div class="entry">
- </div>
當使用塊表達式,可使用{{else}}來指定一個「片斷」,當結果是 falsy value 的時候呈現
- <div class="entry">
- {{#if author}}
- <h1>{{firstName}} {{lastName}}</h1>
- {{else}}
- <h1>Unknown Author</h1>
- {{/if}}
- </div>
The unless
block helper
unless
的做用和if
恰好相反,但表達式返回falsy value的時候渲染block
- <div class="entry">
- {{#unless license}}
- <h3 class="warning">WARNING: This entry does not have a license!</h3>
- {{/unless}}
- </div>
若是當前上下文的license
返回一個falsy value,Handlebars會輸出警告信息,不然什麼都不輸出。
The log
block helper
log
helper容許執行模板的時候輸出當前上下文的狀態
- {{log "Look at me!"}}
信息傳給Handlebars.logger.log
,重寫這個函數能夠實現自定義的log。