Handlebars模板库简单介绍

Handlebars是JavaScript一个语义模板库,通过对view(模板)和data(ajax请求的数据,一般是json)的分离来快速构建Web模板。它采用"Logic-less template"(无逻辑模版)的思路,在加载时被预编译(先对view进行编译生成模板,之后只要把json数据套进去就行了),而不是到了客户端执行到代码时再去编译,这样可以保证模板加载和运行的速度。Handlebars兼容Mustache,你可以在Handlebars中导入Mustache模板。

Handlebars expressions是handlebars模板中最基本的单元,使用方法是加两个花括号{{value}}, handlebars模板会自动匹配相应的数值,对象甚至是函数。

当你想要复用模板的一部分,或者将长模板分割成为多个模板方便维护时,partials就派上用场了。

通过{{}}取出来的内容(把json的数据取到后,显示在模板中时),都会经过编码,也就是说,如果取出的内容中包含html标签,会被转码成纯文本,不会被当成html解析,实际上就是做了类似这样的操作:把<用&lt;替代。这样做是很好的,既可以显示html代码(转码后的html),又可以避免xss注入(避免显示的内容是script,或者href,img等有跨站脚本攻击的标签)。这个功能在做代码展示的时候是非常有用的。但是有时候我们可能需要解析html,不要转码,很简单,把{{}}换成{{{}}}就可以啦。

Handlebars模板库简单使用

<!DOCTYPE html>
 <html>
   <head>
       <title>Handlebars Expressions Example</title>
   </head>
   <body>
       <h1>Handlebars Expressions Example!</h1>
       <div id="list">
       </div>

  <script type="text/javascript" src="script/jquery.js"></script>     //引入jquery插件
       <script type="text/javascript" src="script/handlebars-1.0.0.beta.6.js"></script>    //引入handlebars模板库

  <script id="people-template" type="text/x-handlebars-template">      //显示在页面上的标准模板
         {{#each people}}
      <div class="person">
                 <h2>{{first_name}} {{last_name}}</h2>
                 <div class="phone">{{phone}}</div>
                 <div class="email"><a href="mailto:{{email}}">{{email}}</a></div>
                 <div class="since">User since {{member_since}}</div>
           </div>
         {{/each}}
       </script>

  <script type="text/javascript">
           $(document).ready(function() {    //页面加载完成后,执行
    
               var template = Handlebars.compile($("#people-template").html());

         //先取到标准模板库的元素,然后调用html方法,得到它的内容。由于它的内容是一个handlebars模板,所以可以用Handlebars.compile对这个模板进行预编译。这里讲下jQuery对象html方法:$().html(),取第一个匹配元素的内容。$().html("chaojidan"),设置所有匹配元素的内容。$().html(function(index,content){  return newContent; }) ,index是匹配元素的位置,content是匹配元素的内容,newContent是替换匹配元素内容的新内容。

      var data = {   //后台通过ajax请求到的数据
                 people: [
                     { first_name: "Alan", last_name: "Johnson", phone: "1234567890", email: "alan@test.com", member_since: "Mar 25, 2011" },
                     { first_name: "Allison", last_name: "House", phone: "0987654321", email: "allison@test.com", member_since: "Jan 13, 2011" },
              { first_name: "Nick", last_name: "Pettit", phone: "9836592272", email: "nick@test.com", member_since: "Apr 9, 2009" },
                     { first_name: "Jim", last_name: "Hoskins", phone: "7284927150", email: "jim@test.com", member_since: "May 21, 2010" },
                     { first_name: "Ryan", last_name: "Carson", phone: "8263729224", email: "ryan@test.com", member_since: "Nov 1, 2008" }
                 ]
               };

      $('#list').html(template(data));   //把data对象传进去,模板会自动去匹配数据。模板中取得是data.people属性的值。并且对people循环处理,然后把people数组中的每一项进行输出。最后显示在页面中。
           });
       </script>
   </body>
 </html>

web 开发中,js 解析JSON 是经常的事情。非常繁琐。handlebars 使用了模版,只要你定义一个模版,提供一个json对象,handlebars 就能把json对象放到你定的模版中,非常方便好用!

在模板中也可以使用if语句,if 使用方法很简单,只需要在template中添加{{if}}, 如果有else,也一样,添加{{else}}。Template中代码如下:
 {{#each people}}      
   <div class="person">
     <p>{{title}}          
    {{#if author}}         //people数组中的每一项,如果有author属性,就进入if语句,显示以下html
            {{author.first_name}} {{author.last_name}}</p>
       {{else}}     //没有就显示以下html
            Unknown Author</p>
       {{/if}}
  </div>
{{/each}}

javascript模板引擎恰恰就是为了帮助我们有效的组织数据及其展示内容而出现的。和其它的模板使用方式一样,你需要做如下两个事情:
1. 创建展示模板      var myTemplate = Handlebars.compile($("#table-template").html());  $("#table-template").html()为模板内容

2. 将数据解析到模板中     $('#tableList').html(myTemplate(data));    myTemplate(data)为模板和数据生成的html

我们可以使用with块去定位我们需要的celebrity属性:

如果我们有一个这样的上下文对象:

var shoesData = {groupName:"Celebrities", celebrity:{firstName:"Mike", lastName:"Alexander" } };



<script id="shoe-template" type="x-handlebars-template">
  {{groupName}} Group
    {{#with celebrity}}    //进入到celebrity的上下文
      <li>{{firstName}} {{lastName}}</li>
    {{/with}}
</script>

下面的代码表明了怎样在Handlebars模板中添加注释:

{{! 在这其中的注释表达式不会被输出 }}
你也可使使用一般的HTML注释,但是它们会被输出到HTML页面源文件中,就像一般的HTML注释一样:

<!-- Regular HTML comments will be in the output -->

Handlebars可以使用../来查询当前上下文中的父路径的属性。比如,有一个数据对象如下:

var shoesData = {groupName:"Celebrities", users:[{name:{firstName:"Mike", lastName:"Alexander" }}, {name:{firstName:"John", lastName:"Waters" }} ]};

 
我们可以使用父路径 ../ 来得到groupName属性:

<script id="shoe-template" type="x-handlebars-template">
  {{#users}}     //此种方法也会把users数组中的每一项也输出
    <li>{{name.firstName}} {{name.lastName}} is in the {{../groupName}} group.</li>   //父路径下的groupName属性
  {{/users}}
</script>

unless辅助函数可以增强if,else。下面的代码意思:只有当userLoggedIn属性被检查为假值是其中的内容才会被渲染:

{{#unless userLoggedIn}} Please Log in. {{/unless}}


最后讲一下Handlebars最重要的使用方法:

Handlebars.js自定义辅助函数

Handlebars允许我们添加我们自己的自定义辅助函数,有了自定义辅助函数,我们可以添加任意的Javascript逻辑。我们需要在所有的Handlebars JS代码之前注册自定义辅助函数。自定义辅助函数在Javascript代码中被创建,而不是在Handlebars模板中。

你可以创建两种自定义辅助函数:自定义辅助函数(function helper),它不要使用块表达式就能运行,自定义块辅助函数,它需要和一个块表达式一起运行。

自定义函数辅助函数(function helper)

首先,我们必须用Handlebars.registerHelper方法注册一个自定义辅助函数。这个方法接收一个字符串(辅助函数的名字)作为第一个参数,一个具有任意参数个数的函数作为第二个参数。

Handlebars.registerHelper ("theNameOfTheHelper", function (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" ;
  }

});

下面是一个使用我们刚才创建的自定义函数辅助函数的Handlebars模板:

<script id="shoe-template" type="x-handlebars-template">
  {{#theNameOfTheHelper score}}
</script>

下面是数据var contextObj = {score:85, userName:"Mike"};

最后,把score=85,传入到自定义函数中,返回B。于是模板最终结果返回一个"B"。

自定义块辅助函数

当我们注册了一个自定义块辅助函数时,Handlebars自动在回调函数中添加了一个可选择对象作为最后一个参数。这个可选择对象拥有一个fn方法,一个hash对象,以及一个inverse方法。fn方法接收一个对象(你的数据dataObject[i])作为自定义块表达式模板(<div>{{firstName}} {{lastName}}, Your Total Score is <strong>{{score}}</strong> </div>)中的上下文。你也可以传递任何数据对象,或者如果你想使用引用模板同样的上下文,你可以使用this(dataObject也就是contextObj)。

我们使用Handlebars.registerHelper注册一个userScore的块辅助函数。注意到参数中的最后一个项目是可选择对象,它由Handlebars自动添加:

Handlebars.registerHelper ("userScore", function (dataObject, options) {
  var templateWithInterpolatedData = "";

  for (var i = dataObject.length - 1; i >= 0; i--) {     //遍历dataObject数组
    dataObject[i].score = dataObject[i].score.reduce(function (prev, cur, index, array) {
      return prev + cur;      //数组中的每一项的score属性是一个数组,把这个数组的每一项相加,结果返回给score属性
    });  

    //这里我先介绍一下数组的reduce方法:reduce方法接受两个参数,一个回调方法,一个初始值。callback回调方法接受4个参数:之前值、当前值、索引值以及数组本身。initialValue(初始值)参数可选,表示初始值。若指定,则当作最初使用的previous值;如果缺省,则使用数组的第一个元素作为previous初始值,同时current往后排一位,相比有initialValue值少一次迭代。reduce方法,会把数组的每项进行迭代,最终的结果就是最后return的值。比如:var sum = [1, 2, 3, 4].reduce(function (previous, current, index, array) {return previous + current;});因为没有初始值,所以previous就是数组的第一项,current就是数组的第二项,index值就是当前值的index(当前是1),array就是原数组[1,2,3,4]。第一次返回1+2=3,第二次previous等于上一次返回的值3,current等于当前值3,返回6,第三次previous等于6,当前值4,返回10.这时数组循环结束,把最后的返回结果10,返回给sum(数组调用reduce的结果)。 最终得到的结果就是数组的总和。

    // dataObject[i]变成了{firstName: "Kapil", lastName:"Manish", score:201}

    templateWithInterpolatedData += options.fn (c);

    //将会把对象的数据插入到模板中,也就是把{firstName: "Kapil", lastName:"Manish", score:201}插入到:<div>{{firstName}} {{lastName}}, Your Total Score is <strong>{{score}}</strong> </div>,最后叠加成一个字符串

    

  }

  return templateWithInterpolatedData;     //把所有的数据对象插入到模板后生成的html字符串返回。
});

数据:var contextObj = [{firstName: "Kapil", lastName:"Manish", score:[22, 34, 45, 67]}, {firstName: "Bruce", lastName:"Kasparov", score:[10, 34, 67, 90]}];

模板:

<script id="shoe-template" type="x-handlebars-template">
  {{#userScore this}}     //执行userScore(contextObj)
    <div>{{firstName}} {{lastName}}, Your Total Score is <strong>{{score}}</strong> </div>
  {{/userScore}}
</script>

最终的结果:

HTML的输出结果是:

Bruce Kasparov, Your Total Score is 201

Kapil Manish, Your Total Score is 168

options.inverse方法:

inverse方法在任意块表达式总被当做else部分来使用。因此,当回调函数中的表达式为一个真值是你可以使用options.fn来返回。但是当回调函数中的表达式为假值时你可以使用options.inverse(去渲染else部分中的内容)。

options.hash对象:

Handlebars表达式不接收任何字符串和变量作为参数,但是你依然可以传递用空格分开的键-值对。例如:

(注意到这里没有逗号来分开键-值对变量,是空格)

{{#myNewHelper score=30 firstName="Jhonny" lastName="Marco"}}
  Show your HTML content here.
{{/myNewHelper}}
调用拥有键-值对作为参数的Handlebars表达式将会自动添加到辅助函数回调函数的options.hash对象上。因此:

Handlebars.registerHelper ("myNewHelper", function (dataObject, options) {
  //JSON.stringify用于序列化一个json对象为一个字符串
  console.log(JSON.stringify (options.hash));
  //输出结果为:{score:30, firstName:"Jhonny", lastName:"Marco"}

});

加油!

Handlebars模板库浅析的更多相关文章

  1. handlebars模板库的资源

    web 开发中,js 解析JSON 是经常的事情.非常繁琐.handlebars 使用了模版,只要你定义一个模版,提供一个json对象,handlebars 就能吧json对象放到你定的模版中,非常方 ...

  2. Handlebars 模板引擎之前后端用法

    前言 不知不觉间,居然已经这么久没有写博客了,坚持还真是世界上最难的事情啊. 不过我最近也没闲着,辞工换工.恋爱失恋.深圳北京都经历了一番,这有起有落的生活实在是太刺激了,就如拿着两把菜刀剁洋葱一样, ...

  3. Handlebars模板引擎之上手

    handlebars Handlebars,一个JavaScript模板引擎,是基于Mustache的扩展.模板引擎的都存在一个上下文环境,这是它的作用区间. 需求:基本使用 需要的库 <scr ...

  4. Handlebars模板引擎

    介绍 Handlebars 是 JavaScript 一个语义模板库,通过对view和data的分离来快速构建Web模板.它采用"Logic-less template"(无逻辑模 ...

  5. STL标准模板库(简介)

    标准模板库(STL,Standard Template Library)是C++标准库的重要组成部分,包含了诸多在计算机科学领域里所常见的基本数据结构和基本算法,为广大C++程序员提供了一个可扩展的应 ...

  6. c++转载系列 std::vector模板库用法介绍

    来源:http://blog.csdn.net/phoebin/article/details/3864590 介绍 这篇文章的目的是为了介绍std::vector,如何恰当地使用它们的成员函数等操作 ...

  7. 【转】C++标准库和标准模板库

    C++强大的功能来源于其丰富的类库及库函数资源.C++标准库的内容总共在50个标准头文件中定义.在C++开发中,要尽可能地利用标准库完成.这样做的直接好处包括:(1)成本:已经作为标准提供,何苦再花费 ...

  8. STL标准模板库介绍

    1. STL介绍 标准模板库STL是当今每个从事C++编程的人需要掌握的技术,所有很有必要总结下 本文将介绍STL并探讨它的三个主要概念:容器.迭代器.算法. STL的最大特点就是: 数据结构和算法的 ...

  9. express-8 Handlebars模板引擎(1)

    简介 使用JavaScript生成一些HTML document.write('<h1>Please Don\'t Do This</h1>'); document.write ...

随机推荐

  1. 微信开发之移动手机WEB页面(HTML5)Javascript实现一键拨号及短信发送功能

    在做一个微信的微网站中的一个便民服务电话功能的应用,用到移动web页面中列出的电话号码,点击需要实现调用通讯录,网页一键拨号的拨打电话功能. 如果需要在移动浏览器中实现拨打电话,发送email,美国服 ...

  2. mysql:忘记root密码

    1:修改/etc/my.cnf 2:重启服务 3:进入mysql 4:修改密码 5:刷新权限 注意:修改完成后,别忘了修改/etc/my.cnf,删除skip-grant-tables,否则重启服务后 ...

  3. tony_iptables_01_linux下IPTABLES配置详解(转)

    如果你的IPTABLES基础知识还不了解,建议先去看看. 开始配置 我们来配置一个filter表的防火墙. (1)查看本机关于IPTABLES的设置情况 [root@tp ~]# iptables - ...

  4. Google protobuf proto文件编写规则

    转载自: http://blog.csdn.net/yi_ya/article/details/40404231 1. 简单介绍 protobuf文件:就是定义你要的消息(类似java中的类)和消息中 ...

  5. 作业总结(一):IE6下面的那些坑

    考完试就来实习的公司实习了,大概最近有两周时间就一直在做公司给新人布置的大作业.虽然只是很简单的一个小的项目,但却从其中总结到了不少有用的东西.计划将其发出来一系列文章,算是对这两周时间的总结.也算是 ...

  6. Windows消息机制知识点总结

    1.windows消息类型 以下四种,前三种是系统消息,范围在[0x0000, 0x03ff],第四种是用户自定义消息. 1.1 窗口消息 与窗口的内部运作有关,如创建窗口,绘制窗口,销毁窗口等.可以 ...

  7. 尚学堂Spring视频教程(五):Spring AOP

    在第一节中,我们自己模拟了一个Spring,实现一个保存用户的操作,假如现在有一个需求,在保存的时候记录日志,该怎么做呢? 暂且将记录日志操作就简单的变为在保存用户前输出一句话“save start. ...

  8. delphi.指针.PChar

    此文是delphi.指针.应用姊妹篇,想细化一下PChar应用,所以有了此文. 注意: 1:此文讲的是PChar与字符串相关操作,其它方法暂不多讲. 2:由于D分开Ansi/Unicode的两种完全不 ...

  9. delphi.指针.应用

    注:初稿...有点乱,可能增删改... 因为指针应用,感觉不好写,请大家指出错误,谢谢. 注意: 本文着重点讲的是指针的各类型的应用或使用,而不是说这种方法不应该+不安全+危险+不提倡使用. 其它:本 ...

  10. XShell 无法匹配的outgoing encryption算法 ,No matching outgoing encryption algorithm found

    在链接的属性(SSH -> 安全性) 的加密算法列表中选择 aes256-ctr, mac加密列表中选择hmac-sha2-256,保存即可 To enable hmac-sha2-256 an ...