Handlebars是一个Javascript模板引擎,能让你轻松高效的编写语义化模板,它是Mustache模板引擎的一个扩展,Handlebars和Mustache都是弱逻辑的模板(logic-less template)引擎,能将Web前端的视图和数据分离,降低两者之间耦合。
Handlebars的特点是一切都是表达式,没有操作数据的API,不污染HTML标签,和DeDeCMS、WordPress模板类似,因此能很方便的与其他前端JS库(例如jQuery)混用,并且编写简单,易于扩展。Handlebars支持的浏览器及运行环境有:Internet Explorer 6+、Google Chrome、Firefox、Safari 5+、Opera 11+以及Node.js。Handlebars是Ember.js的默认模板引擎,同时也是基于Node.js的框架Clouda+、Meteor的默认模板引擎。
下载
可以在HandleBars的官方网站下载它的js文件,然后将其加入到你的项目中。如果你的Web项目中已经有一个名为js的文件夹专门放置JavaScript文件,这个位置就是极好的选择。下面的例子在WebStorm中的项目结构如下图所示。
用法
首先在项目中引入HandleBars和jQuery的外部JavaScript文件,注意jQuery不是必须的,但是你必须承认它是一个非常优秀的JavaScript库,它兑现了“写得更少,做得更多”(Write Less, Do More)的承诺,使用jQuery提供的强大的选择器以及它对DOM和Ajax操作的封装还是能省不少事。所以,在下面的项目中我将HandleBars和jQuery都加入到了HTML页面中。
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title>HandleBars Example</title>
</head>
<body>
<script type="text/javascript" src="js/handlebars.js"></script>
<script type="text/javascript" src="js/jquery.js"></script>
</body>
</html>
HandleBars的模板和普通的HTML页面几乎没有区别,我们向上面的代码中加入一段内容。
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title>HandleBars Example</title>
</head>
<body>
<div>
<h1>{{title}}</h1>
<div>
{{greeting}}
</div>
</div>
<script type="text/javascript" src="js/handlebars.js"></script>
<script type="text/javascript" src="js/jquery.js"></script>
</body>
</html>
在上面的代码中,使用了HandleBars的表达式,HandleBars的表达式是写在{{ … }}中的代码。接下来我们将刚才添加的那段代码做成一个模板,做法很简单用一个<script>标签来包围那段代码。
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title>HandleBars Example</title>
</head>
<body>
<script id="foo" type="text/x-handlebars-template">
<div>
<h1>{{title}}</h1>
<div>
{{greeting}}
</div>
</div>
</script>
<script type="text/javascript" src="js/handlebars.js"></script>
<script type="text/javascript" src="js/jquery.js"></script>
</body>
</html>
接下来的工作就是用HandleBars来处理上面的模板,生成页面内容,表达式相当于是模板中的占位符,它会被相应的值替换掉,替换表达式的值可以用JSON方式来书写,代码如下所示。
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title>HandleBars Example</title>
</head>
<body>
<script id="foo" type="text/x-handlebars-template">
<div>
<h1>{{title}}</h1>
<div>
{{greeting}}
</div>
</div>
</script>
<script type="text/javascript" src="js/handlebars.js"></script>
<script type="text/javascript" src="js/jquery.js"></script>
<script type="text/javascript">
var templateSection = $("#foo"); // 获得ID为foo的元素(模板代码段)的jQuery对象
var sourceCode = templateSection.html(); // 获得模板段的HTML代码
var template = Handlebars.compile(sourceCode); // 用Handlebars的compile对模板进行编译
var context = {title:"Hello, world!", greeting:"这是一个使用HandleBars的简单例子"}; // 用JSON保存数据
var targetCode = template(context); // 将模板中的占位符替换成相应的数据得到最终的HTML代码
templateSection.replaceWith(targetCode); // 将原来的模板段替换成最终的HTML代码
</script>
</body>
</html>
需要注意的是,如果替换占位符的字符串中包含实体替换符(如:版权所有©、货币符号¥、右尖括号>),那么在书写HandleBars的表达式时应当用{{{ … }}},可以试一试下面的代码。
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title>HandleBars Example</title>
</head>
<body>
<script id="foo" type="text/x-handlebars-template">
<div>
<!-- 注意这里表达式的写法 -->
<h1>{{{title}}}</h1>
<div>
{{greeting}}
</div>
</div>
</script>
<script type="text/javascript" src="js/handlebars.js"></script>
<script type="text/javascript" src="js/jquery.js"></script>
<script type="text/javascript">
var templateSection = $("#foo");
var sourceCode = templateSection.html();
var template = Handlebars.compile(sourceCode);
var context = {title:"Hello, world! >>", greeting:"这是一个使用HandleBars的简单例子"}; // 注意字符串中有实体替换符
var targetCode = template(context);
templateSection.replaceWith(targetCode);
</script>
</body>
</html>
HandleBars最让人激动的特性应该是块表达式以及自定义帮助器(块表达式处理器),下面的例子演示了块表达式的使用。
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title>HandleBars Example</title>
</head>
<body>
<script id="foo" type="text/x-handlebars-template">
<div>
<h1>{{{title}}}</h1>
<div>
{{greeting}}
</div>
</div>
<!-- 使用块表达式 -->
{{#foreach persons}}
{{name}}: {{age}}
{{/foreach}}
</script>
<script type="text/javascript" src="js/handlebars.js"></script>
<script type="text/javascript" src="js/jquery.js"></script>
<script type="text/javascript">
// 注册一个帮助器(块表达式处理器)
Handlebars.registerHelper("foreach", function(items, options) {
var out = "<ul>";
for(var i = 0, len = items.length; i < len; ++i) {
out += "<li>" + options.fn(items[i]) + "</li>";
}
return out + "</ul>";
});
var templateSection = $("#foo");
var sourceCode = templateSection.html();
var template = Handlebars.compile(sourceCode);
var context = {
title:"Hello, world! >>",
greeting:"这是一个使用HandleBars的简单例子",
persons: [
{name:"Hao LUO", age:34},
{name:"王大锤", age:25},
{name:"张三丰", age:120}
]
};
var targetCode = template(context);
templateSection.replaceWith(targetCode);
</script>
</body>
</html>
再看一个例子吧。
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title>HandleBars Example</title>
</head>
<body>
<script id="foo" type="text/x-handlebars-template">
<div>
<h1>{{{title}}}</h1>
<div>
{{greeting}}
</div>
</div>
{{!-- 下面是一个块表达式 --}}
{{#foreach persons}}
{{f name}}{{t gender}}: {{age}}
{{/foreach}}
</script>
<script type="text/javascript" src="js/handlebars.js"></script>
<script type="text/javascript" src="js/jquery.js"></script>
<script type="text/javascript">
// 注册一个帮助器(块表达式处理器)
Handlebars.registerHelper("foreach", function(items, options) {
var out = "<ul>";
for(var i = 0, len = items.length; i < len; ++i) {
out += "<li>" + options.fn(items[i]) + "</li>";
}
return out + "</ul>";
});
// f帮助器从名字中取出姓氏
Handlebars.registerHelper("f", function(name) {
return name.charAt(0); // 假定都是中文姓名且都是单姓(只是一个小例子而已不要叫真是否合理)
});
// t帮助器根据性别输出先生或女士
Handlebars.registerHelper("t", function(gender) {
return gender ? "先生" : "女士";
});
var templateSection = $("#foo");
var sourceCode = templateSection.html();
var template = Handlebars.compile(sourceCode);
var context = {
title:"Hello, world! >>",
greeting:"这是一个使用HandleBars的简单例子",
persons: [
{name:"骆昊", gender:true, age:34},
{name:"王大锤", gender:false, age:25},
{name:"张三丰", gender:true, age:120}
]
};
var targetCode = template(context);
templateSection.replaceWith(targetCode);
</script>
</body>
</html>
运行效果如下图所示。
当然,HandleBars已经内置了最常用的块处理器。
- if:如果参数值是false、undefined、null、""、0或[],HandlerBars就不会渲染块表达式。代码如下所示:
<div class="entry">
{{#if author}}
<h1>{{firstName}} {{lastName}}</h1>
{{/if}}
</div>
也就是说,上面的代码在上下文中没有author定义的情况下,会产生下面的输出:
<div class="entry">
</div>
- unless:作用与if正好相反。
- each:可以对数组进行迭代。在迭代时还可以使用{{@index}}表示第几次循环,可以用{{@key}}表示对象的属性名。
<ul class="person_list">
{{#each persons}}
<li>{{this}}</li>
{{/each}}
</ul>
上下文数据如下所示:
{ persons:["骆昊", "王大锤", "张三丰"] }
更多的内容可以关注HandleBars的官方网站关于内置帮助器的内容。
可以使用jQuery封装的Ajax函数从服务器获取JSON格式的上下文数据,代码如下所示:
$.getJSON("HelloServlet", {}, function(context) {
var targetCode = template(context);
templateSection.replaceWith(targetCode);
});
HandleBars的官方网站还提供了HandleBars的参考手册。