Handlebars 模板引擎
百度百科这样解释模板:模板是将一个事物的结构规律予以固定化、标准化的成果,它体现的是结构形式的标准化
handlebars的出现,解决了远古时期,使用字符串拼接标签的尬局,而handlebars作为模板引擎,将html结构固化,数据以变量的形式代替,这样html更容易维护,开发更方便,这种开发模式也导致前端mvc框架的出现。
场景例子:
远古时期的查询列表的列表数据回显:
// 在ajax请求的返回结果里面
// 返回的数据结构为 data = ['张三','李四','王五']
var str = '';
for (var i = 0; i < data.length; i++) {
str += '<tr>';
str += '<td>' + data[i].name + '</td>';
...
str += '</tr>';
}
$('#tbodyId').html(str);
近代时期handlebars的查询列表的列表数据回显:
// 在html页面里面先写一个handlebars模板
<script id="tbody-template" type="text/x-handlebars-template">
{{#each this}}
<tr>
<td>{{name}}</td>
</tr>
{{/end}}
</script>
// 在ajax请求的返回结果里面
// 返回的数据结构为 data = ['张三','李四','王五']
var tbodyTemp = Handlebars.compile($('#tbody-template').html());
$('#tbodyId').html(tbodyTemp(data));
现在应该了解了handlebars的用处,现在看下具体用法。
官方网站:·http://handlebarsjs.com/
下载地址:点击下载
以下要点:
+ Handlebars模板是写在<script></script>
标签里面的,并且要注明这个标签的类型type="text/x-handlebars-template
+ 变量是以{{}}
双换括号来取值的
+ 使用思路:
1. 要先将模板编译为js语言:var tbodyTemp = Handlebars.compile($('#tbody-template').html())
2. 再使用返回的方法传入数据data
来生成html:tbodyTemp(data)
。传入的data可以是数组可以是对象
3. 最后放入页面的html页面对应的标签中:$('#tbodyId').html(tbodyTemp(data))
+ 支持结构语法,判断语法,不支持直接在双花括号中运算
下面主要看模板的写法:
循环结构each语法:
{{#each this}} // 循环语句开始 this指向传入的数据结构 data => tbodyTemp(data)
<li>{{this}}</li> // 要循环的html结构
{{/end}} // 循环语句结束
提示:
1. 如果传入的数据结构是对象data = {names:['张三','李四','王五']}
,可以下面这样取{{#each names}}
,一般我们都取到数组后再传入js方法:tbodyTemp(data.names)
。
2. 如果传入的数据结构是数组对象,下面这样
data = [
{
name:'张三',
age:23
},
{
name:'李四',
age:20
}
]
下面这样取值:
<script id="tbody-template" type="text/x-handlebars-template">
{{#each this}} // this 为 数组的每一个元素对象
<tr>
<td>{{name}}</td> // name 为this.name
<td>{{age}}</td> // age 为this.age
</tr>
{{/each}}
</script>
with语法:
width的用处是进入到某个属性(进入到某个上下文环境),比如我们的数组的每个对象元素还有数组,这时候就要使用with进入的子数组里面,然后在循环字数组
比如数据结构是这样的:
data = [
{
name:'张三',
results:[
{
subject:'语文',
result:99
},
{
subject:'数学',
result:100
}
]
}
]
这个时候循环子数组:
<script id="tbody-template" type="text/x-handlebars-template">
{{#each this}}
<tr>
<td>{{name}}</td>
{{#with results}} // 进入子数组
{{#each this}} // 循环子数组
<td>{{subject}}</td> // 子数组每个对象的值
<td>{{result}}</td>
{{/each}}
{{/with}}
</tr>
{{/each}}
</script>
if判断语法:
if 判断 没啥说的直接看代码:
/*
data = [
{
name:'张三',
},
{
name:'李四',
age:23
}
]
*/
<script id="tbody-template" type="text/x-handlebars-template">
{{#each this}}
<tr>
<td>{{name}}</td>
{{#if age}}
<td>{{age}}</td>
{{else}} // 这两行也可以不用写,直接判断age存在时显示内容
<td>未知年龄</td> // 这两行也可以不用写,直接判断age存在时显示内容
{{/if}}
</tr>
{{/each}}
</script>
helper助手:
helper,可译为助手的意思,说白了就是帮助你来完成某些功能。
比如:
我想判断某个值等于1时才显示对应的标签结构,否则显示另外的标签结构;又或者我想把某个值格式化为2位小数显示等等
helper主要有两种用法:
1. 处理某个值的显示方式
2. 替代if功力不足,而使用的高级点的判断
处理某个值的显示方式
上面说了取值是用{{}}来取值,但是取到这个值我想格式化一下再显示出来,这个时候我们需要注册一个helper助手
// js中
Handlebars.registerHelper('formatNumber', function(value) {
return value.toFixed(2);
});
// 模板中这样使用
<script id="tbody-template" type="text/x-handlebars-template">
{{#each this}}
<tr>
<td>{{formatNumber amount}}</td> //formatNumber为上面注册的helper
</tr>
{{/each}}
</script>
替代if功力不足,而使用的高级点的判断
if只能判断值存不存在,基本上没多大用处,这事我们就需要注册一个高级的判断helper助手
比如:我们想判断某个值等于1显示对应的结构,否则显示另外的结构
// js中
Handlebars.registerHelper("compare",function(v1,v2,options){
if(v1 == v2){
//满足添加继续执行
return options.fn(this); // 固定写法
}else{
//不满足条件执行{{else}}部分
return options.inverse(this); // 固定写法
}
});
// js数据结构
data = [
{
name:'张三',
age:23,
isDelete:1
},
{
name:'李四',
age:23,
isDelete:0
}
]
// 模板中这样使用
<script id="tbody-template" type="text/x-handlebars-template">
{{#each this}}
<tr>
<td>{{name}}</td>
{{#compare isDelete 1}}
<td>该人已被删除</td>
{{else}}
<td>存在,年龄为{{age}}</td>
{{/compare}}
</tr>
{{/each}}
</script>
当然我们也可以定义一个通用的compare判断助手
var operators = {
'==': function(l, r) {return l == r; },
'===': function(l, r) {return l === r; },
'!=': function(l, r) {return l != r; },
'!==': function(l, r) {return l !== r; },
'<': function(l, r) {return l < r; },
'>': function(l, r) {return l > r; },
'<=': function(l, r) {return l <= r; },
'>=': function(l, r) {return l >= r; },
'typeof': function(l, r) {return typeof l == r; }
};
Handlebars.registerHelper('compare', function(left, operator, right, options) {
if (arguments.length < 3) {
throw new Error('Handlerbars Helper "compare" 需要3个参数');
}
if (!operators[operator]) {
throw new Error('Handlerbars Helper "compare" 不存在的操作符:' + operator);
}
var result = operators[operator](left, right);
if (result) {
return options.fn(this);
} else {
return options.inverse(this);
}
});
Handlebars预编译模板js引入用法:
采用Handlebars预编译模板js,可以不用handlebars.js
文件,这时可以引入一个更小的文件handlebars.runtime.js
,当然也可以引入handlebars.js
,不冲突下面。说下这种用法:
1、首先我们需要在本地全局安装handlebars,使用nodejs包管理器来安装npm install -g handlebars
2、建立模板文件list
,并在里面写入html模板内容,注意此时不用在写<script>
标签了
3、使用handlebars命令来编译模板文件handlebars list -f list.js
4、在页面中引入list.js
文件
5、通过js来调用编译后的jsvar html = Handlebars.templates.list(data)