Handlebars简介
Handlebars 是 JavaScript 一个语义模板库,通过对view和data的分离来快速构建Web模板。它采用”Logic-less template”(无逻辑模版)的思路,在加载时被预编译,而不是到了客户端执行到代码时再去编译,这样可以保证模板加载和运行的速度。
虽然是无逻辑,但还是有一些简单的逻辑比如if、each等。
可以拿Handlebars的语法风格和一般普通js+html混合的风格作对比:
1
2
3
4
5
6
7
8//js+html
1 <% if (names.length) { %>
2 <ul>
3 <% names.forEach(function(name){ %>
4 <li><%= name %></li>
5 <% }) %>
6 </ul>
7 <% } %>1
2
3
4
5
6
7
8//Handlebars
1 {{#if names.length}}
2 <ul>
3 {{#each names}}
4 <li>{{this}}</li>
5 {{/each}}
6 </ul>
7 {{/if}}看上去一目了然多了。
基本语法
- 基本语法很简单,主要就是用大括号将data包括起来:
- {{data}} 两个会将内容做html编码转换。
- {{{data}}} 三个则不会转码,如果输入一个html标签,是真的会得到一个标签。
块级表达式
这个也很容易懂,可以定义一个数据块,以#开头,以/结尾,如:
1
2
3
4{{#list people}}
{{firstName}}
{{lastName}}
{{/list}}内容渲染:
1
2
3
4
5
6
7{
people: [
{firstName: "Yehuda", lastName: "Katz"},
{firstName: "Carl", lastName: "Lerche"},
{firstName: "Alan", lastName: "Johnson"}
]
}输出结果:
1
2
3
4
5<ul>
<li>Yehuda Katz</li>
<li>Carl Lerche</li>
<li>Alan Johnson</li>
</ul>
路径
Handlebars支持嵌套的属性,使得用模板处理JSON字符串成为可能。如:
1
2
3
4
5
6
7
8<div class="entry">
<h1>{{title}}</h1>
<h2>By {{author.name}}</h2>
<div class="body">
{{body}}
</div>
</div>1
2
3
4
5
6
7
8var context = {
title: "My First Blog Post!",
author: {
id: 47,
name: "Yehuda Katz"
},
body: "My first post. Wheeeee!"
};可以用../语法,相当于当前路径的父级,如:
1
2
3
4
5
6
7
8
9
101 var post = {
2 title: "Blog Post!",
3 author: [{
4 id: 47,
5 name: "Jack"
6 },{
7 id: 20,
8 name: "Mark"
9 }]
10 };1
2
3
4
5
6
7
8
9
101 {{#post}}
2 {{#if author.length}}
3 <h3>{{title}}</h3>
4 <ul>
5 {{#each author}}
6 <li>{{../title}}s author is {{name}}</li>
7 {{/each}}
8 </ul>
9 {{/if}}
10 {{/post}}li标签里面已经是在 author 字段之内了,所以要使用 ‘../‘ 来转到上层的 title。
Hepler
each
可以使用内置的{{#each}} helper遍历列表块内容,用this来引用遍历的元素 例如:1
2
3
4
5<ul>
{{#each name}}
<li>{{this}}</li>
{{/each}}
</ul>1
2
3{
name: ["html","css","javascript"]
};if else
{{#if}}就像使用JavaScript一样,可以指定条件渲染DOM。如果if返回的条件是false,undefined, null, “” 或者 [],则不会渲染DOM;如果存在{{#else}}则执行{{#else}}后面的渲染,如:1
var data = {info:['HTML5','CSS3',"WebGL"],"error":"数据取出错误"}
1
2
3
4
5
6
7
8
9{{#if list}}
<ul id="list">
{{#each list}}
<li>{{this}}</li>
{{/each}}
</ul>
{{else}}
<p>{{error}}</p>
{{/if}}{{#if}}判断是否存在list数组,如果存在则遍历list,如果不存在输出错误信息。
unless
即反向的if else语法,当判定值为false时渲染DOM,如:1
2
3
4
5
6
7
8
9{{#unless data}}
<ul id="list">
{{#each list}}
<li>{{this}}</li>
{{/each}}
</ul>
{{else}}
<p>{{error}}</p>
{{/unless}}with
这种情况是返回的json数据有多个对象嵌套的问题,很好用的一个方法,也可以直接通过对象点属性的方法找下去。
{{#with}}一般情况下,Handlebars模板会在编译的阶段的时候进行context传递和赋值。使用with的方法,我们可以将context转移到数据的一个section里面(如果你的数据包含section)。 这个方法在操作复杂的template时候非常有用。1
2
3
4
5
6<div class="entry">
<h1>{{title}}</h1>
{{#with author}}
<h2>By {{firstName}} {{lastName}}</h2>
{{/with}}
</div>1
2
3
4
5
6
7{
title: "My first post!",
author: {
firstName: "Charles",
lastName: "Jolley"
}
}
关于Fish里的hbs
RequireJS导入hbs模板,并使用Backbone的View加载出来。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15define([
'hbs!modules/order/order-entry/templates/customer-home-tabs/components/AccountInfoTpl.hbs',
'i18n!modules/order/order-entry/i18n/OrderEntry'
], function (AccountInfoTpl, I18N) {
return portal.BaseView.extend({
template: AccountInfoTpl,
serialize: I18N,
events: {
},
initialize: function (initOptions) {
},
afterRender: function () {
},
})
});模板示例
1
2
3
4
5
6
7
8
9
10<div class="col-md-12 col-xl-12">
<div class="btn-toolbar pull-right">
<button type="button" class="btn btn-min-width btn-primary js-edit">{{COMMON_MODIFY}}</button>
<button type="button" class="btn btn-default js-modify-history-pop">{{ORDER_ENTRY_CUSTOMER_MODIFY_HISTORY}}</button>
</div>
<div class="btn-toolbar pull-right" style="display:none">
<button type="button" class="btn btn-min-width btn-primary js-ok">{{COMMON_OK}}</button>
<button type="button" class="btn btn-min-width btn-default js-cancel">{{COMMON_CANCEL}}</button>
</div>
</div>I18N示例
1
2
3define({
ORDER_ENTRY_CUSTOMER_MODIFY_HISTORY: "Modify History"
});