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的参考手册。