Handlebars模板库浅析

Handlebars模板库简单介绍javascript

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

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

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

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

Handlebars模板库简单使用ajax

<!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());    express

         //先取到标准模板库的元素,而后调用html方法,获得它的内容。因为它的内容是一个handlebars模板,因此能够用Handlebars.compile对这个模板进行预编译。这里讲下jQuery对象html方法:$().html(),第一个匹配元素内容。$().html("chaojidan"),设置全部匹配元素的内容。$().html(function(index,content){  return newContent; }) ,index是匹配元素的位置,content是匹配元素的内容,newContent是替换匹配元素内容的新内容。json


               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>api

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"}

});

 

 

加油!

相关文章
相关标签/搜索