handlebars.js初学
handlebars.js初学
a.简介-introduction
Handlebars 是 JavaScript 一个语义模板库,通过对view和data的分离来快速构建web模板。
它采用”Logic-less template”(无逻辑模版)的思路,在加载时被预编译,而不是到了客户端执行到代码时再去编译,这样可以保证模板加载和运行的速度。
利用Handlebars处理HTML模板时,一般步骤如下:
- 获取模板内容
- 预编译模板
- 模板数据填充
- 将结果追加到页面中
Handlebars兼容Mustache,你可以在Handlebars中导入Mustache模板。
b.安装-install
去handlebarsjs官方网站http://handlebarsjs.com/ 直接下载handlebars.js,用<script>标签引入,
也可通过NPM和Bower安装,详见http://handlebarsjs.com/installation.html
Getting Started
Handlebars expressions 是handlebars模板中最基本的单元,使用方法是加两个花括号{{value}}, handlebars模板会自动匹配相应的数值,对象甚至是函数
例如:
1
2
3
4
5
6
7
8
<div class="entry">
<h1>{{title}}</h1>
<div class="body">
{{body}}
</div>
</div>
你可以使用”script”标签引入handlebars模板:
1
2
3
4
5
6
7
8
9
10
<script id="entry-template" type="text/x-handlebars-template">
<div class="entry">
<h1>{{title}}</h1>
<div class="body">
{{body}}
</div>
</div>
</script>
在javascript中使用Handlebars.compile编译模板
1
2
var source = $("#entry-template").html();
var template = Handlebars.compile(source);
你也可以预编译你的模板,然后只需引入更小的运行时库(handlebars.runtime.js),避免在浏览器中编译,提高性能,这在移动设备中显得更重要。
完整例子-直接在HTML中渲染
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>创建第一个 handlebars 应用</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/4.0.5/handlebars.min.js"></script>
</head>
<body>
<div id="entry">
<h1>{{title}}</h1>
<div class="body">
{{body}}
</div>
</div>
<script type="text/javascript">
var context = {title: "My New Post", body: "This is my first post!"};
//1.获取模板内容
var source = document.getElementById("entry").innerHTML;
//2.预编译模板
var template = Handlebars.compile(source);
//3.模板数据填充
var html = template(context);
//4.将结果追加到页面
document.getElementById("entry").innerHTML = html;
</script>
</body>
</html>
完整例子-借用”script”标签
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>创建第一个 handlebars 应用</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/4.0.5/handlebars.min.js"></script>
</head>
<body>
<div id="demo">
<script id="entry-template" type="text/x-handlebars-template">
<div class="entry">
<h1>{{title}}</h1>
<div class="body">
{{body}}
</div>
</div>
</script>
</div>
<script type="text/javascript">
var context = {title: "My New Post", body: "This is my first post!"};
//1.获取模板内容
var source = $("#entry-template").html();
//2.预编译模板
var template = Handlebars.compile(source);
//3.模板数据填充
var html = template(context);
//4.将结果追加到页面
$("#demo").html(html);
</script>
</body>
</html>
results in
1
2
3
4
5
6
<div id="entry">
<h1>My New Post</h1>
<div class="body">
This is my first post!
</div>
</div>
HTML编码
在handlebars里,{{expression}}会返回一个经过编码的HTML,也就是说,如果取出的内容中包含html标签,会被转码成纯文本,不会被当成html解析,实际上就是做了类似这样的操作:把<
用 <
替代。如果你不希望被编码,可以使用{{{
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>handlebars-html编码</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/4.0.5/handlebars.min.js"></script>
</head>
<body>
<div id="entry">
<h1>{{title}}</h1>
<div class="body">
{{{body}}}
</div>
</div>
<script type="text/javascript">
var context = {
title: "All about <p> Tags",
body: "<p>This is a post about <p> tags</p>"
};
var source = $("#entry").html();
var template = Handlebars.compile(source);
var html = template(context);
$("#entry").html(html);
</script>
</body>
</html>
results in
1
2
3
4
5
6
<div id="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)。此时,你需要手动对内容进行编码:
1
2
3
4
5
6
7
8
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也不会再次编码了。
块表达式-Block Expressions
块表达式在Handlebars中由一个代码块,一个开标志{{#}},一个闭合标志{{/}}组成。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>handlebars-块表达式</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/4.0.5/handlebars.min.js"></script>
</head>
<body>
<div id="demo">
{{#list people}} {{firstName}} {{lastName}} {{/list}}
</div>
<script type="text/javascript">
var data = {
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){ //true
//console.log('items:',items === data.people);
//console.log('this:',this === data); //true
//console.log('options.fn(this):',options.fn(items[0]));
var out = "<ul>";
for(var i=0,l=items.length;i<l;i++){
out += "<li>" + options.fn(items[i]) + "</li>";
}
return out + "</ul>";
})
var tpl = $("#demo").html();
var template = Handlebars.compile(tpl);
var html = template(data);
$("#demo").html(html);
</script>
</body>
</html>
results in
1
2
3
4
5
<ul>
<li>Yehuda Katz</li>
<li>Carl Lerche</li>
<li>Alan Johnson</li>
</ul>
当我们注册了一个自定义块辅助函数时,Handlebars自动在回调函数中添加了一个可选择对象作为最后一个参数。这个可选择对象拥有一个fn方法,一个hash对象,以及一个inverse方法
options.fn方法:
fn方法接收一个对象(你的数据)作为它在自定义辅助函数块模板中作为上下文来使用的参数。你可以传递任何数据对象,或者如果你想使用引用模板的同样的上下文
路径-paths
Handlebars支持简单的路径,也支持嵌套路径,可以查找下一级的属性
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>handlebars-路径</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/4.0.5/handlebars.min.js"></script>
</head>
<body>
<div class="entry">
<h1></h1>
<h2>By {{author.name}}</h2>
<div class="body">
{{body}}
</div>
</div>
<script type="text/javascript">
var context = {
title: "My First Blog Post!",
author: {
id: 47,
name: "Yehuda Katz"
},
body: "My first post. Wheeeee!"
};
var tpl = $(".entry").html();
var template = Handlebars.compile(tpl);
var html = template(context);
$(".entry").html(html);
</script>
</body>
</html>
嵌套路径同样支持../
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>handlebars-路径</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/4.0.5/handlebars.min.js"></script>
</head>
<body>
<div class="entry">
<div id="comments">
{{#each comments}}
<h2><a href="/posts/{{../permalink}}#{{id}}">{{title}}</a></h2>
<div>{{body}}</div>
{{/each}}
</div>
</div>
<script type="text/javascript">
var data = {
permalink:'http://keenwon.com',
comments: [
{id:1,title:'链接1',body:'链接1'},
{id:2,title:'链接2',body:'链接2'}
]
};
var tpl = $(".entry").html();
var template = Handlebars.compile(tpl);
var html = template(data);
$(".entry").html(html);
</script>
</body>
</html>
模板注释 {{! }} or {{!– –}}
1
2
3
4
5
6
7
8
9
10
11
<div class="entry">
{{! 我是单行注释 }}
{{msg}}
{{!-- 我是
多行注释
--}}
</div>
each循环
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>each循环</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/4.0.5/handlebars.min.js"></script>
</head>
<body>
<table id="tableList">
<script id="table-template" type="text/x-handlebars-template">
{{#each student}}
<tr>
<td>{{name}}</td>
<td>{{sex}}</td>
<td>{{age}}</td>
</tr>
{{/each}}
</script>
</table>
<script type="text/javascript">
$(document).ready(function() {
//模拟的json对象
var data = {
"student": [
{
"name": "张三",
"sex": "0",
"age": 18
},
{
"name": "李四",
"sex": "0",
"age": 22
},
{
"name": "妞妞",
"sex": "1",
"age": 18
}
]
};
//注册一个Handlebars模版,通过id找到某一个模版,获取模版的html框架
var myTemplate = Handlebars.compile($("#table-template").html());
//将json对象用刚刚注册的Handlebars模版封装,得到最终的html,插入到基础table中。
$('#tableList').html(myTemplate(data));
});
</script>
</body>
</html>
指定上下文:with
with指令可以转移上下文环境,让当前的上下文进入到一个属性中
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>with</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/4.0.5/handlebars.min.js"></script>
</head>
<body>
<table id="tableList">
<script id="table-template" type="text/x-handlebars-template">
{{#each this}}
<tr>
<td>{{name}}</td>
<td>{{sex}}</td>
<td>{{age}}</td>
<td>
{{#with favorite}}
{{#each this}}
<p>{{name}}</p>
{{/each}}
{{/with}}
</td>
</tr>
{{/each}}
</script>
</table>
<script type="text/javascript">
$(document).ready(function() {
var data = [
{
"name": "张三",
"sex": "0",
"age": 18,
"favorite":
[
{
"name":"唱歌"
},{
"name":"篮球"
}
]
},
{
"name": "李四",
"sex": "0",
"age": 22,
"favorite":
[
{
"name":"上网"
},{
"name":"足球"
}
]
},
];
var tpl = $("#table-template").html();
var template = Handlebars.compile(tpl);
var html = template(data);
$("#tableList").html(html);
});
</script>
</body>
</html>
{{#with favorite}}表示进入到favorite属性的上下文中,而favorite属性中又是一个list,因此可以用{{#each this}}进行遍历,表示遍历当前上下文环境,对于每次遍历,都是map结构,取name属性,最终拿到所有兴趣爱好。
with可以结合handlebars的路径访问一起使用。Handlebars提供了.来访问属性也可以使用../来访问父级属性。
1
2
3
4
5
6
7
8
{{#with person}}
<h1>{{../company.name}}</h1>
{{/with}}
//对应的json数据
{
"person": { "name": "Alan" },
company: {"name": "Rad, Inc." }
}
this的使用
this表示当前的上下文
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>with</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/4.0.5/handlebars.min.js"></script>
</head>
<body>
<div id="tableList">
<script id="table-template" type="text/x-handlebars-template">
{{#each this}}
<p>{{this}}</p>
{{/each}}
</script>
</div>
<script type="text/javascript">
$(document).ready(function() {
var data = {
"name": "张三",
"sex": "0",
"age": 18
};
var myTemplate = Handlebars.compile($("#table-template").html());
$('#tableList').html(myTemplate(data));
});
</script>
</body>
</html>
if、unless
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>with</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/4.0.5/handlebars.min.js"></script>
</head>
<body>
<div id="demo">
<script id="table-template" type="text/x-handlebars-template">
{{#if list}}
<ul id="list">
{{#each list}}
<li>{{this}}</li>
{{/each}}
</ul>
{{else}}
<p>{{err}}</p>
{{/if}}
</script>
</div>
<script type="text/javascript">
$(document).ready(function() {
var data = {
list: ['HTML5','CSS3',"WebGL"],
err: "数据取出错误",
list2: [ ],
list3: { }
}
var tpl = $("#table-template").html();
var template = Handlebars.compile(tpl);
var html = template(data);
$("#demo").html(html);
});
</script>
</body>
</html>
对于if指令,如果返回的为undefined、null、”“、[ ]、{ }、false任意一个,都会导致最终结果为假。
unless则是和if指令相反,当判断的值为false时他会渲染DOM
自定义函数辅助函数(function helper)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>自定义函数</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/4.0.5/handlebars.min.js"></script>
</head>
<body>
<div id="demo">
<script id="table-template" type="text/x-handlebars-template">
{{theNameOfTheHelper score}}
</script>
</div>
<script type="text/javascript">
$(document).ready(function() {
var data = {score:85, userName:"Mike"};
Handlebars.registerHelper ("theNameOfTheHelper", function (theScore) {
console.log("Grade: " + theScore );
if (theScore >= 90) {
return "A" ;
}
else if (theScore >= 80 && theScore < 90) {
return "B" ;
}
else if (theScore >= 70 && theScore < 80) {
return "C" ;
}
else {
return "D" ;
}
});
var tpl = $("#table-template").html();
var template = Handlebars.compile(tpl);
var html = template(data);
$("#demo").html(html);
});
</script>
</body>
</html>