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. 读写hdfs文件(工作笔记)

    import java.io.IOException; import java.io.InputStream; import java.util.List; import java.util.Map; ...

  2. PCB设计中的20H原则

    20H原则是指电源层相对地层内缩20H的距离,当然也是为抑制边缘辐射效应.在板的边缘会向外辐射电磁干扰.将电源层内缩,使得电场只在接地层的范围内传导.有效的提高了EMC.若内缩20H则可以将70%的电 ...

  3. HBase参数配置及说明

    版本:0.94-cdh4.2.1 hbase-site.xml配置 hbase.tmp.dir 本地文件系统tmp目录,一般配置成local模式的设置一下,但是最好还是需要设置一下,因为很多文件都会默 ...

  4. java如何区分是form表单请求,还是ajax请求

    requestType = request.getHeader("X-Requested-With");                 if(requestType==null) ...

  5. [手机取证] 绕过屏幕锁定启用调试模式-For Android 4.4.2

    Google在Android 4.x中引入了调试信任机制,类似于iOS,在设备有屏幕密码的情况下首次连接(或未记住计算机)的情况下, 需要首先打开屏幕锁定后才可进行调试启用操作. 在Android 4 ...

  6. php面向对象学习笔记

    PHP 面向对象技术(全面讲解) Ø 主要内容 v 1.面向对象的概念 v 2.什么是类,什么是对象,类和对象之间的关系 v 3.什么是面向对象编程呢? v 4.如何抽象出一个类? v 5.如何实例化 ...

  7. AX 2012 template table use in Query

    queryRuntmp = new QueryRun(querytmp); queryRuntmp.setRecord(arAgingForLeasingTmp); while(queryRuntmp ...

  8. Hadoop内功修炼

    IT十八掌<大数据内功修炼系列课程>强势推出!由实战派名师徐培成亲自操刀,学完做不了大数据我们负全责!2015.12.21前,优惠价:4999(名额已不多!)2015.12.31前,优惠价 ...

  9. Xilinx FPGA全局时钟和全局时钟资源的使用方法

    对FPGA的全局时钟了解不多,遂转载一篇文档: http://xilinx.eetop.cn/?action-viewnews-itemid-42 目前,大型设计一般推荐使用同步时序电路.同步时序电路 ...

  10. Java Docs

    1 Java Docs on Oracle:   1.1 Online(EN): JavaSE6  http://docs.oracle.com/javase/6/docs/api/index.htm ...