zoukankan      html  css  js  c++  java
  • js模版引擎handlebars.js实用教程

    一、为什么选择Handlebars.js

      据小菜了解,对于java开发,涉及到页面展示时,比较主流的有两种解决方案:

           1. struts2+vo+el表达式。

           这种方式,重点不在于struts2,而是vo和el表达式,其基本思想是:根据页面需要的信息,构造出一个实体,这个实体中包含了界面需要的所有属性,通常这个实体是由N个表中的字段构成的,俗称vo。由于vo的属性可以是String、List、Map等等等,又可以vo套vo,因此这种方式非常灵活,也非常好用。

           在后台对vo进行赋值,通过struts2封装到request中,然后在界面用el表达式,通常是${}、forEach标签什么的,即可构造出界面。

           但这种方式小菜却不是很看好。因为这种利用标签控制html,依然是把表现和控制混杂在一起,html里边混杂了大量el控制标签,很不美观。

           当然,小菜不可能因为这么简单的理由拒绝这种方式,读者仔细思考可以发现,利用el表达式生成html代码,这是一个在服务器端执行的动作,在服务器端解析完成之后,才发送到客户端浏览器上,这样做会占用大量服务器资源,而且速度缓慢。

             示例代码:

     1 <c:forEach var='bm' items="${contractAuditVo.borrowerModels}">
     2   <table>
     3     <tbody>
     4       <tr>
     5         <td>借款人编号:</td>
     6         <td>
     7           <p>
     8             ${bm.borrowerId }
     9           </p>
    10         </td>
    11       </tr>
    12       <tr>
    13         <td>客户编号:</td>
    14         <td>
    15           <p>
    16             ${bm.customerId }
    17           </p>
    18         </td>
    19       </tr>
    20       <tr>
    21         <td>曾用名:</td>
    22         <td>
    23           <p>
    24             ${bm.usedName }
    25           </p>
    26         </td>
    27       </tr>
    28     </tbody>
    29   </table>
    30 </c:forEach>

     2. Json+ajax+拼html

             这种方法一般是基于ajax请求,要求服务器端返回一个json类型的json字符串,这个json串中包含了界面所需的所有信息,界面拿到json串后,构造出html,完成界面展示。

             小菜推荐这种方法,通过这种方式编写的页面,反应速度非常快,用户体验非常好。

             因为服务器端只需要提供一个json串,由客户端完成解析,因此服务器承受的压力很小,目前的电脑配置都较高,客户端的浏览器解析js脚本很快,因此页面体验效果好。

             解析的过程大致是通过Jquery的each方法,进行遍历。

             但是小菜利用这种方式时,犯了一个致命的错误,小菜是通过原始的拼接html的方式,页面中写了大量html+=”<div>”;,这种写法使页面变得非常凌乱,几乎不可以维护。

             示例代码:

     1 var contractTextHtml="";
     2 $.each(jsonObject.cl,function(i,n){
     3   
     4   contractTextHtml="";
     5   
     6   //插入合同文本数据
     7   contractTextHtml+="<div title='出借人信息---"+hiddenNull(n.cm.lenderName)+"' style='overflow:auto;padding:5px;'>";
     8   contractTextHtml+="<table class='ui-table ui-table-noborder'>";
     9   contractTextHtml+="<tbody>";
    10   contractTextHtml+="<tr><td>合同编号:</td><td><p>"+hiddenNull(n.cm.contractId)+"</p></td></tr>";
    11   contractTextHtml+="<tr class='ui-table-split'><td>出借人姓名:</td><td><p>"+hiddenNull(n.cm.lenderName)+"</p></td></tr>";
    12   contractTextHtml+="<tr><td>出借人证件类型:</td><td><p>"+hiddenNull(n.cm.lenderIdType)+"</p></td></tr>";
    13   contractTextHtml+="<tr class='ui-table-split'><td>出借人证件号:</td><td><p>"+hiddenNull(n.cm.lenderIdNum)+"</p></td></tr>";
    14   contractTextHtml+="<tr><td>出借金额:</td><td><p>"+hiddenNull(n.cm.lenderAmount)+"</p></td></tr>";
    15   contractTextHtml+="<tr class='ui-table-split'><td>出借人编号:</td><td><p>"+hiddenNull(n.cm.lenderNo)+"</p></td></tr>";
    16   contractTextHtml+="<tr><td>出借人银行帐号:</td><td><p>"+hiddenNull(n.cm.lenderBankAccount)+"</p></td></tr>";
    17   contractTextHtml+="<tr class='ui-table-split'><td>撮合编号:</td><td><p>"+hiddenNull(n.cm.makeMatchNo)+"</p></td></tr>";
    18   contractTextHtml+="</tbody>";
    19   contractTextHtml+="</table>";
    20   contractTextHtml+="</div>";
    21   $("#textList").append(contractTextHtml);
    22 });

       造成这种问题的根本原因在于拼接html打乱了html原有的层次结构,看不出来哪里是哪里,没有了层次结构的代码,堆在那里就像是一坨垃圾。

             el表达式构造html优点是能够保持html原有格式,js构造html优点是速度快省资源,为什么我们不能把二者的优点结合在一起呢?这就是Handlebars.js。

             既然要在项目中引入js模版引擎,就必须进行技术选型,严格考核之后,才可以引入,就好像是木桶效应,不能让他成为项目中的短板。

             Handlebars.js是一款基于Jquery的插件,以json对象为数据源,支持逻辑判断、循环等操作,同时具有非常好的扩展性,体积60KB左右,经过小菜仔细的分析研究,这是一款不可多得的js模版引擎。 

    二、如何引入Handlebars.js

      Jquery插件,第一步当然要引用Jquery啦,然后引用Handlebars.js即可,仅仅需要这两个js文件。

    1 <script type="text/javascript" src="script/jquery.js"></script>
    2 <script type="text/javascript" src="script/handlebars-1.0.0.beta.6.js"></script>

    三、each-基本循环使用方法。

     1 <!DOCTYPE html>
     2 <html>
     3   <head>
     4     <META http-equiv=Content-Type content="text/html; charset=utf-8">
     5     <title>each-基本循环使用方法 - by 杨元</title>
     6   </head>
     7   <body>
     8     <h1>each-基本循环使用方法</h1>
     9     <!--基础html框架-->
    10     <table>
    11       <thead>
    12         <tr>
    13           <th>姓名</th>
    14           <th>性别</th>
    15           <th>年龄</th>
    16         </tr>
    17       </thead>
    18       <tbody id="tableList">
    19         
    20       </tbody>
    21     </table>
    22     
    23     <!--插件引用-->
    24     <script type="text/javascript" src="script/jquery.js"></script>
    25     <script type="text/javascript" src="script/handlebars-1.0.0.beta.6.js"></script>
    26     
    27     <!--Handlebars.js模版-->
    28     <!--Handlebars.js模版放在script标签中,保留了html原有层次结构,模版中要写一些操作语句-->
    29     <!--id可以用来唯一确定一个模版,type是模版固定的写法-->
    30     <script id="table-template" type="text/x-handlebars-template">
    31       {{#each student}}
    32         <tr>
    33           <td>{{name}}</td>
    34           <td>{{sex}}</td>
    35           <td>{{age}}</td>
    36         </tr> 
    37       {{/each}}
    38     </script>
    39     
    40     <!--进行数据处理、html构造-->
    41     <script type="text/javascript">
    42       $(document).ready(function() {
    43         //模拟的json对象
    44         var data = {
    45                     "student": [
    46                         {
    47                             "name": "张三",
    48                             "sex": "0",
    49                             "age": 18
    50                         },
    51                         {
    52                             "name": "李四",
    53                             "sex": "0",
    54                             "age": 22
    55                         },
    56                         {
    57                             "name": "妞妞",
    58                             "sex": "1",
    59                             "age": 18
    60                         }
    61                     ]
    62                 };
    63         
    64         //注册一个Handlebars模版,通过id找到某一个模版,获取模版的html框架
    65         //$("#table-template").html()是jquery的语法,不懂的童鞋请恶补。。。
    66         var myTemplate = Handlebars.compile($("#table-template").html());
    67         
    68         //将json对象用刚刚注册的Handlebars模版封装,得到最终的html,插入到基础table中。
    69         $('#tableList').html(myTemplate(data));
    70       });
    71     </script>
    72   </body>
    73 </html>

      通过阅读本例,读者已经掌握Handlebars.js一个重要特性:循环。#each可以理解成循环命令,循环的是json对象中的student属性。对于每次循环,都可以读出里边的name、sex、age属性。

      

    四、each-循环中使用this

     1 <!DOCTYPE html>
     2 <html>
     3   <head>
     4     <META http-equiv=Content-Type content="text/html; charset=utf-8">
     5     <title>each-循环中使用this - by 杨元</title>
     6   </head>
     7   <body>
     8     <h1>each-循环中使用this</h1>
     9     <!--基础html框架-->
    10     <table>
    11       <thead>
    12         <tr>
    13           <th>姓名</th>
    14           <th>性别</th>
    15           <th>年龄</th>
    16         </tr>
    17       </thead>
    18       <tbody id="tableList">
    19         
    20       </tbody>
    21     </table>
    22     
    23     <!--插件引用-->
    24     <script type="text/javascript" src="script/jquery.js"></script>
    25     <script type="text/javascript" src="script/handlebars-1.0.0.beta.6.js"></script>
    26     
    27     <!--Handlebars.js模版-->
    28     <!--Handlebars.js模版放在script标签中,保留了html原有层次结构,模版中要写一些操作语句-->
    29     <!--id可以用来唯一确定一个模版,type是模版固定的写法-->
    30     <script id="table-template" type="text/x-handlebars-template">
    31       {{#each this}}
    32         <tr>
    33           <td>{{name}}</td>
    34           <td>{{sex}}</td>
    35           <td>{{age}}</td>
    36         </tr> 
    37       {{/each}}
    38     </script>
    39     
    40     <!--进行数据处理、html构造-->
    41     <script type="text/javascript">
    42       $(document).ready(function() {
    43         //模拟的json对象
    44         var data = [
    45                         {
    46                             "name": "张三",
    47                             "sex": "0",
    48                             "age": 18
    49                         },
    50                         {
    51                             "name": "李四",
    52                             "sex": "0",
    53                             "age": 22
    54                         },
    55                         {
    56                             "name": "妞妞",
    57                             "sex": "1",
    58                             "age": 18
    59                         }
    60                     ];
    61         
    62         //注册一个Handlebars模版,通过id找到某一个模版,获取模版的html框架
    63         //$("#table-template").html()是jquery的语法,不懂的童鞋请恶补。。。
    64         var myTemplate = Handlebars.compile($("#table-template").html());
    65         
    66         //将json对象用刚刚注册的Handlebars模版封装,得到最终的html,插入到基础table中。
    67         $('#tableList').html(myTemplate(data));
    68       });
    69     </script>
    70   </body>
    71 </html>

         很多时候,我们拿到的json对象,本身就是一个list,并不是map,直接就可以遍历,不需要#each student这样指定遍历某个属性。

         此时可以用#each this,表示遍历当前对象。

         this表示当前上下文,非常灵活,以后还会提及,读者可以举一反三。

    五、each嵌套

     1 <!DOCTYPE html>
     2 <html>
     3   <head>
     4     <META http-equiv=Content-Type content="text/html; charset=utf-8">
     5     <title>each嵌套 - by 杨元</title>
     6   </head>
     7   <body>
     8     <h1>each嵌套</h1>
     9     <!--基础html框架-->
    10     <div id="dataList"></div>
    11     
    12     <!--插件引用-->
    13     <script type="text/javascript" src="script/jquery.js"></script>
    14     <script type="text/javascript" src="script/handlebars-1.0.0.beta.6.js"></script>
    15     
    16     <!--Handlebars.js模版-->
    17     <!--Handlebars.js模版放在script标签中,保留了html原有层次结构,模版中要写一些操作语句-->
    18     <!--id可以用来唯一确定一个模版,type是模版固定的写法-->
    19     <script id="table-template" type="text/x-handlebars-template">
    20       {{#each this}}
    21         {{#each info}}
    22           {{../name}}的{{this}}<br>
    23         {{/each}}
    24       {{/each}}
    25     </script>
    26     
    27     <!--进行数据处理、html构造-->
    28     <script type="text/javascript">
    29       $(document).ready(function() {
    30         //模拟的json对象
    31          var data = [{
    32                       "name":"张三",
    33                       "info":[
    34                         "眼睛",
    35                         "耳朵",
    36                         "鼻子"
    37                       ]
    38                     },{
    39                       "name":"李四",
    40                       "info":[
    41                         "爸爸",
    42                         "妈妈",
    43                         "妻子"
    44                       ]
    45                     }];
    46         
    47         //注册一个Handlebars模版,通过id找到某一个模版,获取模版的html框架
    48         //$("#table-template").html()是jquery的语法,不懂的童鞋请恶补。。。
    49         var myTemplate = Handlebars.compile($("#table-template").html());
    50         
    51         //将json对象用刚刚注册的Handlebars模版封装,得到最终的html,插入到基础table中。
    52         $('#dataList').html(myTemplate(data));
    53       });
    54     </script>
    55   </body>
    56 </html>

              循环嵌套在稍微复杂点的页面设计中即会涉及,Handlebars.js完全支持each嵌套,可以在each中使用each。

              上边的例子演示了两个关键点:each嵌套的可实现性、如何在each嵌套中读取父each中的数据。

              例子很简单,info本身是一个信息列表,是属于某个人的,我们先用each遍历所有的人,然后再遍历每个人的info信息,这样就形成了each嵌套。但是我们想在内层each中获取外层each的数据,达到“谁的什么”这样的显示效果。

              显然,如果直接在内层each中使用{{name}},是取不到任何数据的,因为内层each的上下文是info,而name属性在表示人的上下文中。

              此时,可以用{{../name}}从内层each获取上一级each的name属性,语法和html的路径表示一样,简单吧?

    六、循环中使用索引

     1 <!DOCTYPE html>
     2 <html>
     3   <head>
     4     <META http-equiv=Content-Type content="text/html; charset=utf-8">
     5     <title>关于循环中索引的使用 - by 杨元</title>
     6   </head>
     7   <body>
     8     <h1>关于循环中索引的使</h1>
     9     <!--基础html框架-->
    10     <table>
    11       <thead>
    12         <tr>
    13           <th>序号</th>
    14           <th>姓名</th>
    15           <th>性别</th>
    16           <th>年龄</th>
    17         </tr>
    18       </thead>
    19       <tbody id="tableList">
    20         
    21       </tbody>
    22     </table>
    23     
    24     <!--插件引用-->
    25     <script type="text/javascript" src="script/jquery.js"></script>
    26     <!--注意!这个例子用的是新版本handlebars,旧版本不支持-->
    27     <script type="text/javascript" src="script/handlebars-v1.3.0.js"></script>
    28     
    29     <!--Handlebars.js模版-->
    30     <!--Handlebars.js模版放在script标签中,保留了html原有层次结构,模版中要写一些操作语句-->
    31     <!--id可以用来唯一确定一个模版,type是模版固定的写法-->
    32     <script id="table-template" type="text/x-handlebars-template">
    33       {{#each student}}
    34       <tr>
    35         <td>{{addOne @index}}</td>
    36         <td>{{name}}</td>
    37         <td>{{sex}}</td>
    38         <td>{{age}}</td>
    39       </tr>
    40       {{/each}}
    41     </script>
    42     
    43     <!--进行数据处理、html构造-->
    44     <script type="text/javascript">
    45       $(document).ready(function() {
    46         //模拟的json对象
    47          var data = {
    48                       "student": [
    49                           {
    50                               "name": "张三",
    51                               "sex": "0",
    52                               "age": 18
    53                           },
    54                           {
    55                               "name": "李四",
    56                               "sex": "0",
    57                               "age": 22
    58                           },
    59                           {
    60                               "name": "妞妞",
    61                               "sex": "1",
    62                               "age": 19
    63                           }
    64                       ]
    65                   };
    66         
    67         //注册一个Handlebars模版,通过id找到某一个模版,获取模版的html框架
    68         //$("#table-template").html()是jquery的语法,不懂的童鞋请恶补。。。
    69         var myTemplate = Handlebars.compile($("#table-template").html());
    70         
    71         //注册一个Handlebars Helper,用来将索引+1,因为默认是从0开始的
    72         Handlebars.registerHelper("addOne",function(index,options){
    73           return parseInt(index)+1;
    74         });
    75         
    76         //将json对象用刚刚注册的Handlebars模版封装,得到最终的html,插入到基础table中。
    77         $('#tableList').html(myTemplate(data));
    78       });
    79     </script>
    80   </body>
    81 </html>

         序号是指:在循环过程中,当前循环的索引,说白了,就是当前为第几次循环,一般从0开始,Handlebars.js中也是如此。

         有什么用呢?最常见的是在显示table的时候,给每行加一个序号,清晰的展示出页面上共有多少条记录,如上边的例子。

         除此之外,小菜为了在循环中区分不同的id,恰好需要一个序号,确保id不重复,用过bootstrap的童鞋应该知道,好多事件可以通过id定位,例如Listgroup控件。

         废话少说,在Handlebars.js中,可以通过{{@index}}来获取当前的索引,也就是说@index这个变量就代表了当前索引。

         在上边的例子里,table的序号从0开始不太好,于是注册了一个Helper,将索引+1。

    七、Handlebars.js循环中索引(@index)使用技巧(访问父级索引)

         使用Handlebars.js过程中,难免会使用循环,比如构造数据表格。而使用循环,又经常会用到索引,也就是获取当前循环到第几次了,一般会以这个为序号显示在页面上。

         Handlebars.js中获取循环索引很简单,只需在循环中使用{{@index}}即可。

     1 <!DOCTYPE html>
     2 <html>
     3   <head>
     4     <META http-equiv=Content-Type content="text/html; charset=utf-8">
     5     <title>Handlebars.js循环中索引(@index)使用技巧 - by 杨元</title>
     6   </head>
     7   <body>
     8     <h1>Handlebars.js循环中索引(@index)使用技巧</h1>
     9     <!--基础html框架-->
    10     <table>
    11       <thead>
    12         <tr>
    13           <th></th>
    14           <th>姓名</th>
    15           <th>性别</th>
    16           <th>年龄</th>
    17         </tr>
    18       </thead>
    19       <tbody id="tableList">
    20         
    21       </tbody>
    22     </table>
    23     
    24     <!--插件引用-->
    25     <script type="text/javascript" src="script/jquery.js"></script>
    26     <script type="text/javascript" src="script/handlebars-v1.3.0.js"></script>
    27     
    28     <!--Handlebars.js模版-->
    29     <!--Handlebars.js模版放在script标签中,保留了html原有层次结构,模版中要写一些操作语句-->
    30     <!--id可以用来唯一确定一个模版,type是模版固定的写法-->
    31     <script id="table-template" type="text/x-handlebars-template">
    32       {{#each this}}
    33         <tr>
    34           <td>{{@index}}.</td>
    35           <td>{{name}}</td>
    36           <td>{{sex}}</td>
    37           <td>{{age}}</td>
    38         </tr>
    39       {{/each}}
    40     </script>
    41     
    42     <!--进行数据处理、html构造-->
    43     <script type="text/javascript">
    44       var data = [{
    45         name: "张三",
    46         sex: "",
    47         age: 35
    48       },{
    49         name: "李四",
    50         sex: "",
    51         age: 23
    52       },{
    53         name: "甜妞",
    54         sex: "",
    55         age: 18
    56       }];
    57       
    58       //解析模版
    59       var handle = Handlebars.compile($("#table-template").html());
    60       //生成html
    61       var html = handle(data);
    62       //插入到页面
    63       $("#tableList").append(html);
    64       
    65     </script>
    66   </body>
    67 </html>
    View Code

          虽然用{{@index}}可以获取到索引,但遗憾的是,索引是从0开始的。。。这样让人看起来很不舒服。因此,我们可以使用一个Helper来让索引+1,变成从1开始。

     1 <!DOCTYPE html>
     2 <html>
     3   <head>
     4     <META http-equiv=Content-Type content="text/html; charset=utf-8">
     5     <title>Handlebars.js循环中索引(@index)使用技巧 - by 杨元</title>
     6   </head>
     7   <body>
     8     <h1>Handlebars.js循环中索引(@index)使用技巧</h1>
     9     <!--基础html框架-->
    10     <table>
    11       <thead>
    12         <tr>
    13           <th></th>
    14           <th>姓名</th>
    15           <th>性别</th>
    16           <th>年龄</th>
    17         </tr>
    18       </thead>
    19       <tbody id="tableList">
    20         
    21       </tbody>
    22     </table>
    23     
    24     <!--插件引用-->
    25     <script type="text/javascript" src="script/jquery.js"></script>
    26     <script type="text/javascript" src="script/handlebars-v1.3.0.js"></script>
    27     
    28     <!--Handlebars.js模版-->
    29     <!--Handlebars.js模版放在script标签中,保留了html原有层次结构,模版中要写一些操作语句-->
    30     <!--id可以用来唯一确定一个模版,type是模版固定的写法-->
    31     <script id="table-template" type="text/x-handlebars-template">
    32       {{#each this}}
    33         <tr>
    34           <td>{{addOne @index}}.</td>
    35           <td>{{name}}</td>
    36           <td>{{sex}}</td>
    37           <td>{{age}}</td>
    38         </tr>
    39       {{/each}}
    40     </script>
    41     
    42     <!--进行数据处理、html构造-->
    43     <script type="text/javascript">
    44       var data = [{
    45         name: "张三",
    46         sex: "",
    47         age: 35
    48       },{
    49         name: "李四",
    50         sex: "",
    51         age: 23
    52       },{
    53         name: "甜妞",
    54         sex: "",
    55         age: 18
    56       }];
    57       
    58       //注册索引+1的helper
    59       var handleHelper = Handlebars.registerHelper("addOne",function(index){
    60         //返回+1之后的结果
    61         return index+1;
    62       });
    63       //解析模版
    64       var handle = Handlebars.compile($("#table-template").html());
    65       //生成html
    66       var html = handle(data);
    67       //插入到页面
    68       $("#tableList").append(html);
    69       
    70     </script>
    71   </body>
    72 </html>
    View Code

          不要以为这就完事了,这只是一般情况,小菜还要介绍一个非常特殊的场景。

          假如循环中套了一个循环,在内层循环中如何获取外层循环的索引呢?

          我们已经知道,可以用类似{{../name}}这种语法访问父级循环中的属性,但是这样访问父级索引是不可以的,例如:{{../@index}},这样写是不正确的。

          我们可以通过一个小手段来获取。

          写例子之前,小菜多废话几句,其实这个非常实用,可以创建分级的索引,比如1.1、1.2等,也可以用作特殊的标识,理解成分组。

      1 <!DOCTYPE html>
      2 <html>
      3   <head>
      4     <META http-equiv=Content-Type content="text/html; charset=utf-8">
      5     <title>Handlebars.js循环中索引(@index)使用技巧 - by 杨元</title>
      6   </head>
      7   <body>
      8     <h1>Handlebars.js循环中索引(@index)使用技巧</h1>
      9     <!--基础html框架-->
     10     <table>
     11       <thead>
     12         <tr>
     13           <th></th>
     14           <th>姓名</th>
     15           <th>性别</th>
     16           <th>年龄</th>
     17         </tr>
     18       </thead>
     19       <tbody id="tableList">
     20         
     21       </tbody>
     22     </table>
     23     
     24     <!--插件引用-->
     25     <script type="text/javascript" src="script/jquery.js"></script>
     26     <script type="text/javascript" src="script/handlebars-v1.3.0.js"></script>
     27     
     28     <!--Handlebars.js模版-->
     29     <!--Handlebars.js模版放在script标签中,保留了html原有层次结构,模版中要写一些操作语句-->
     30     <!--id可以用来唯一确定一个模版,type是模版固定的写法-->
     31     <script id="table-template" type="text/x-handlebars-template">
     32       {{#each this}}
     33         <tr>
     34           <td>{{addOne @index}}</td>
     35           <td>{{name}}</td>
     36           <td>{{sex}}</td>
     37           <td>{{age}}</td>
     38         </tr>
     39         {{#each family}}
     40           <tr>
     41             <td>{{../_index}}.{{@index}}</td>
     42             <td>{{name}}</td>
     43             <td>{{sex}}</td>
     44             <td>{{age}}</td>
     45           </tr>
     46         {{/each}}
     47       {{/each}}
     48     </script>
     49     
     50     <!--进行数据处理、html构造-->
     51     <script type="text/javascript">
     52       var data = [{
     53         name: "张三",
     54         sex: "",
     55         age: 35,
     56         family: [{
     57           name: "张三儿子",
     58           sex: "",
     59           age: 10,
     60         },{
     61           name: "张三妻子",
     62           sex: "",
     63           age: 33,
     64         }]
     65       },{
     66         name: "李四",
     67         sex: "",
     68         age: 23,
     69         family: [{
     70           name: "李四妻子",
     71           sex: "",
     72           age: 23,
     73         }]
     74       },{
     75         name: "甜妞",
     76         sex: "",
     77         age: 18,
     78         family: [{
     79           name: "甜妞妈妈",
     80           sex: "",
     81           age: 40,
     82         },{
     83           name: "甜妞爸爸",
     84           sex: "",
     85           age: 43,
     86         },{
     87           name: "甜妞姥爷",
     88           sex: "",
     89           age: 73,
     90         }]
     91       }];
     92       
     93       //注册索引+1的helper
     94       var handleHelper = Handlebars.registerHelper("addOne",function(index){
     95         //利用+1的时机,在父级循环对象中添加一个_index属性,用来保存父级每次循环的索引
     96         this._index = index+1;
     97         //返回+1之后的结果
     98         return this._index;
     99       });
    100       //解析模版
    101       var handle = Handlebars.compile($("#table-template").html());
    102       //生成html
    103       var html = handle(data);
    104       //插入到页面
    105       $("#tableList").append(html);
    106       
    107     </script>
    108   </body>
    109 </html>
    View Code

    八、with-进入到某个属性(进入到某个上下文环境)

      1 <!DOCTYPE html>
      2 <html>
      3   <head>
      4     <META http-equiv=Content-Type content="text/html; charset=utf-8">
      5     <title>with-进入到某个属性(进入到某个上下文环境) - by 杨元</title>
      6   </head>
      7   <body>
      8     <h1>with-进入到某个属性(进入到某个上下文环境)</h1>
      9     <!--基础html框架-->
     10     <table>
     11       <thead>
     12         <tr>
     13           <th>姓名</th>
     14           <th>性别</th>
     15           <th>年龄</th>
     16           <th>兴趣爱好</th>
     17         </tr>
     18       </thead>
     19       <tbody id="tableList">
     20         
     21       </tbody>
     22     </table>
     23     
     24     <!--插件引用-->
     25     <script type="text/javascript" src="script/jquery.js"></script>
     26     <script type="text/javascript" src="script/handlebars-1.0.0.beta.6.js"></script>
     27     
     28     <!--Handlebars.js模版-->
     29     <!--Handlebars.js模版放在script标签中,保留了html原有层次结构,模版中要写一些操作语句-->
     30     <!--id可以用来唯一确定一个模版,type是模版固定的写法-->
     31     <script id="table-template" type="text/x-handlebars-template">
     32       {{#each this}}
     33         <tr>
     34           <td>{{name}}</td>
     35           <td>{{sex}}</td>
     36           <td>{{age}}</td>
     37           <td>
     38             {{#with favorite}}
     39               {{#each this}}
     40                 <p>{{name}}</p>
     41               {{/each}}
     42             {{/with}}
     43           </td>
     44         </tr> 
     45       {{/each}}
     46     </script>
     47     
     48     <!--进行数据处理、html构造-->
     49     <script type="text/javascript">
     50       $(document).ready(function() {
     51         //模拟的json对象
     52         var data = [
     53                         {
     54                             "name": "张三",
     55                             "sex": "0",
     56                             "age": 18,
     57                             "favorite":
     58                             [
     59                               {
     60                                 "name":"唱歌"
     61                               },{
     62                                 "name":"篮球"
     63                               }
     64                             ]
     65                         },
     66                         {
     67                             "name": "李四",
     68                             "sex": "0",
     69                             "age": 22,
     70                             "favorite":
     71                             [
     72                               {
     73                                 "name":"上网"
     74                               },{
     75                                 "name":"足球"
     76                               }
     77                             ]
     78                         },
     79                         {
     80                             "name": "妞妞",
     81                             "sex": "1",
     82                             "age": 18,
     83                             "favorite":
     84                             [
     85                               {
     86                                 "name":"电影"
     87                               },{
     88                                 "name":"旅游"
     89                               }
     90                             ]
     91                         }
     92                     ];
     93         
     94         //注册一个Handlebars模版,通过id找到某一个模版,获取模版的html框架
     95         //$("#table-template").html()是jquery的语法,不懂的童鞋请恶补。。。
     96         var myTemplate = Handlebars.compile($("#table-template").html());
     97         
     98         //将json对象用刚刚注册的Handlebars模版封装,得到最终的html,插入到基础table中。
     99         $('#tableList').html(myTemplate(data));
    100       });
    101     </script>
    102   </body>
    103 </html>

      在循环每名学生时,学生的favorite属性并不是一个普通的字符串,而又是一个json对象,确切的说是一个list,我们需要把学生的爱好全部取出来。

         这时候就需要with命令,这个命令可以让当前的上下文进入到一个属性中,{{#with favorite}}表示进入到favorite属性的上下文中,而favorite属性中又是一个list,因此可以用{{#each this}}进行遍历,表示遍历当前上下文环境,对于每次遍历,都是map结构,取name属性,最终拿到所有兴趣爱好。

    九、with-终极this应用

     1 <!DOCTYPE html>
     2 <html>
     3   <head>
     4     <META http-equiv=Content-Type content="text/html; charset=utf-8">
     5     <title>with-终极this应用 - by 杨元</title>
     6   </head>
     7   <body>
     8     <h1>with-终极this应用</h1>
     9     <!--基础html框架-->
    10     <table>
    11       <thead>
    12         <tr>
    13           <th>姓名</th>
    14           <th>性别</th>
    15           <th>年龄</th>
    16           <th>兴趣爱好</th>
    17         </tr>
    18       </thead>
    19       <tbody id="tableList">
    20         
    21       </tbody>
    22     </table>
    23     
    24     <!--插件引用-->
    25     <script type="text/javascript" src="script/jquery.js"></script>
    26     <script type="text/javascript" src="script/handlebars-1.0.0.beta.6.js"></script>
    27     
    28     <!--Handlebars.js模版-->
    29     <!--Handlebars.js模版放在script标签中,保留了html原有层次结构,模版中要写一些操作语句-->
    30     <!--id可以用来唯一确定一个模版,type是模版固定的写法-->
    31     <script id="table-template" type="text/x-handlebars-template">
    32       {{#each this}}
    33         <tr>
    34           <td>{{name}}</td>
    35           <td>{{sex}}</td>
    36           <td>{{age}}</td>
    37           <td>
    38             {{#with favorite}}
    39               {{#each this}}
    40                 <p>{{this}}</p>
    41               {{/each}}
    42             {{/with}}
    43           </td>
    44         </tr> 
    45       {{/each}}
    46     </script>
    47     
    48     <!--进行数据处理、html构造-->
    49     <script type="text/javascript">
    50       $(document).ready(function() {
    51         //模拟的json对象
    52         var data = [
    53                         {
    54                             "name": "张三",
    55                             "sex": "0",
    56                             "age": 18,
    57                             "favorite":
    58                             [
    59                               "唱歌",
    60                               "篮球"
    61                             ]
    62                         },
    63                         {
    64                             "name": "李四",
    65                             "sex": "0",
    66                             "age": 22,
    67                             "favorite":
    68                             [
    69                               "上网",
    70                               "足球"
    71                             ]
    72                         },
    73                         {
    74                             "name": "妞妞",
    75                             "sex": "1",
    76                             "age": 18,
    77                             "favorite":
    78                             [
    79                               "电影",
    80                               "旅游"
    81                             ]
    82                         }
    83                     ];
    84         
    85         //注册一个Handlebars模版,通过id找到某一个模版,获取模版的html框架
    86         //$("#table-template").html()是jquery的语法,不懂的童鞋请恶补。。。
    87         var myTemplate = Handlebars.compile($("#table-template").html());
    88         
    89         //将json对象用刚刚注册的Handlebars模版封装,得到最终的html,插入到基础table中。
    90         $('#tableList').html(myTemplate(data));
    91       });
    92     </script>
    93   </body>
    94 </html>

         本例和上例不同之处在于favorite属性中不再是map项,而是普通字符串,因此对于每个项,可以直接用{{this}}读取,this代表当前字符串。

         所以说,this非常灵活,读者一定要大胆发挥想象力。 

    十、if-判断的基本用法

     1 <!DOCTYPE html>
     2 <html>
     3   <head>
     4     <META http-equiv=Content-Type content="text/html; charset=utf-8">
     5     <title>if-判断的基本用法 - by 杨元</title>
     6   </head>
     7   <body>
     8     <h1>if-判断的基本用法</h1>
     9     <!--基础html框架-->
    10     <table>
    11       <thead>
    12         <tr>
    13           <th>姓名</th>
    14           <th>性别</th>
    15           <th>年龄</th>
    16         </tr>
    17       </thead>
    18       <tbody id="tableList">
    19         
    20       </tbody>
    21     </table>
    22     
    23     <!--插件引用-->
    24     <script type="text/javascript" src="script/jquery.js"></script>
    25     <script type="text/javascript" src="script/handlebars-1.0.0.beta.6.js"></script>
    26     
    27     <!--Handlebars.js模版-->
    28     <!--Handlebars.js模版放在script标签中,保留了html原有层次结构,模版中要写一些操作语句-->
    29     <!--id可以用来唯一确定一个模版,type是模版固定的写法-->
    30     <script id="table-template" type="text/x-handlebars-template">
    31       {{#each student}}
    32         {{#if name}}
    33           <tr>
    34             <td>{{name}}</td>
    35             <td>{{sex}}</td>
    36             <td>{{age}}</td>
    37           </tr>
    38         {{/if}}
    39       {{/each}}
    40     </script>
    41     
    42     <!--进行数据处理、html构造-->
    43     <script type="text/javascript">
    44       $(document).ready(function() {
    45         //模拟的json对象
    46         var data = {
    47                     "student": [
    48                         {
    49                             "name": "张三",
    50                             "sex": "0",
    51                             "age": 18
    52                         },
    53                         {
    54                             "sex": "0",
    55                             "age": 22
    56                         },
    57                         {
    58                             "name": "妞妞",
    59                             "sex": "1",
    60                             "age": 18
    61                         }
    62                     ]
    63                 };
    64         
    65         //注册一个Handlebars模版,通过id找到某一个模版,获取模版的html框架
    66         //$("#table-template").html()是jquery的语法,不懂的童鞋请恶补。。。
    67         var myTemplate = Handlebars.compile($("#table-template").html());
    68         
    69         //将json对象用刚刚注册的Handlebars模版封装,得到最终的html,插入到基础table中。
    70         $('#tableList').html(myTemplate(data));
    71       });
    72     </script>
    73   </body>
    74 </html>

         在遍历student时,由于数据缺失,并不是每一个学生都有name属性,我们不想显示没有name属性的学生,这时就需要if来做判断。

         {{#if name}}可以用来判断当前上下文中有没有name属性,实际上,它是尝试去读取name属性,如果返回的为undefined、null、""、[]、false任意一个,都会导致最终结果为假。

         if还支持多层次读取,例如:{{#if name.xxx}},这样写就假设name属性是一个map,检测name属性中是否包含xxx属性。 

    十一、由于if功力不足引出的Helper

     1 <!DOCTYPE html>
     2 <html>
     3   <head>
     4     <META http-equiv=Content-Type content="text/html; charset=utf-8">
     5     <title>由于if功力不足引出的Helper - by 杨元</title>
     6   </head>
     7   <body>
     8     <h1>由于if功力不足引出的Helper</h1>
     9     <!--基础html框架-->
    10     <table>
    11       <thead>
    12         <tr>
    13           <th>姓名</th>
    14           <th>性别</th>
    15           <th>年龄</th>
    16         </tr>
    17       </thead>
    18       <tbody id="tableList">
    19         
    20       </tbody>
    21     </table>
    22     
    23     <!--插件引用-->
    24     <script type="text/javascript" src="script/jquery.js"></script>
    25     <script type="text/javascript" src="script/handlebars-1.0.0.beta.6.js"></script>
    26     
    27     <!--Handlebars.js模版-->
    28     <!--Handlebars.js模版放在script标签中,保留了html原有层次结构,模版中要写一些操作语句-->
    29     <!--id可以用来唯一确定一个模版,type是模版固定的写法-->
    30     <script id="table-template" type="text/x-handlebars-template">
    31       {{#each student}}
    32         {{#if name}}
    33           {{#compare age 20}}
    34             <tr>
    35               <td>{{name}}</td>
    36               <td>{{sex}}</td>
    37               <td>{{age}}</td>
    38             </tr>
    39           {{else}}
    40             <tr>
    41               <td>?</td>
    42               <td>?</td>
    43               <td>?</td>
    44             </tr>
    45           {{/compare}}
    46         {{/if}}
    47       {{/each}}
    48     </script>
    49     
    50     <!--进行数据处理、html构造-->
    51     <script type="text/javascript">
    52       $(document).ready(function() {
    53         //模拟的json对象
    54         var data = {
    55                     "student": [
    56                         {
    57                             "name": "张三",
    58                             "sex": "0",
    59                             "age": 23
    60                         },
    61                         {
    62                             "sex": "0",
    63                             "age": 22
    64                         },
    65                         {
    66                             "name": "妞妞",
    67                             "sex": "1",
    68                             "age": 18
    69                         }
    70                     ]
    71                 };
    72         
    73         //注册一个Handlebars模版,通过id找到某一个模版,获取模版的html框架
    74         //$("#table-template").html()是jquery的语法,不懂的童鞋请恶补。。。
    75         var myTemplate = Handlebars.compile($("#table-template").html());
    76         
    77         //注册一个比较大小的Helper,判断v1是否大于v2
    78         Handlebars.registerHelper("compare",function(v1,v2,options){
    79           if(v1>v2){
    80             //满足添加继续执行
    81             return options.fn(this);
    82           }else{
    83             //不满足条件执行{{else}}部分
    84             return options.inverse(this);
    85           }
    86         });
    87         
    88         //将json对象用刚刚注册的Handlebars模版封装,得到最终的html,插入到基础table中。
    89         $('#tableList').html(myTemplate(data));
    90       });
    91     </script>
    92   </body>
    93 </html>

             很多时候,我们需要更加复杂的if判断逻辑,显然默认的if不能满足我们的需求。

             本例中,利用Handlebars.js中Helper强大的扩展性,定义了一个compare,它用来比较两个数的大小,如果第一个数大于第二个数,满足条件继续执行,否则执行{{else}}部分。

             Handlebars.registerHelper用来定义Helper,它有两个参数,第一个参数是Helper名称,第二个参数是一个回调函数,用来执行核心业务逻辑。本例中的函数,有三个参数,其中前两个参数是需要比较的两个数,第三个参数是固定的,就叫options,如果加了该参数,就说明这个Helper是一个Block,块级别的Helper,有一定的语法结构,调用的时候加#号,就像if那样。

             关于options的使用,小菜所了解的就是这种用法,return options.fn(this);表示满足条件继续执行,也就是执行{{#compare }}和{{else}}之间的代码;return options.inverse(this);表示不满足条件,也就是执行{{else}}和{{/compare}}之间的代码。

             由于这是一个块级别的Helper,所以调用要加#,例如:{{#compare age 20}},其中的age就是当前上下文中读取到的年龄,20是小菜随便写的值,意思是只要age比20大,就显示,否则全显示?。

             读者可以看出,Helper中写的可以是任何js代码,现在想想,就知道Handlebars有多灵活了吧!!

    十二、另一种Helper用法

      1 <!DOCTYPE html>
      2 <html>
      3   <head>
      4     <META http-equiv=Content-Type content="text/html; charset=utf-8">
      5     <title>另一种Helper用法 - by 杨元</title>
      6   </head>
      7   <body>
      8     <h1>另一种Helper用法</h1>
      9     <!--基础html框架-->
     10     <table>
     11       <thead>
     12         <tr>
     13           <th>姓名</th>
     14           <th>性别</th>
     15           <th>年龄</th>
     16         </tr>
     17       </thead>
     18       <tbody id="tableList">
     19         
     20       </tbody>
     21     </table>
     22     
     23     <!--插件引用-->
     24     <script type="text/javascript" src="script/jquery.js"></script>
     25     <script type="text/javascript" src="script/handlebars-1.0.0.beta.6.js"></script>
     26     
     27     <!--Handlebars.js模版-->
     28     <!--Handlebars.js模版放在script标签中,保留了html原有层次结构,模版中要写一些操作语句-->
     29     <!--id可以用来唯一确定一个模版,type是模版固定的写法-->
     30     <script id="table-template" type="text/x-handlebars-template">
     31       {{#each student}}
     32         {{#if name}}
     33           {{#compare age 20}}
     34             <tr>
     35               <td>{{name}}</td>
     36               <td>{{transformat sex}}</td>
     37               <td>{{age}}</td>
     38             </tr>
     39           {{else}}
     40             <tr>
     41               <td>?</td>
     42               <td>?</td>
     43               <td>?</td>
     44             </tr>
     45           {{/compare}}
     46         {{/if}}
     47       {{/each}}
     48     </script>
     49     
     50     <!--进行数据处理、html构造-->
     51     <script type="text/javascript">
     52       $(document).ready(function() {
     53         //模拟的json对象
     54         var data = {
     55                     "student": [
     56                         {
     57                             "name": "张三",
     58                             "sex": "0",
     59                             "age": 23
     60                         },
     61                         {
     62                             "name": "李四",
     63                             "sex": "0",
     64                             "age": 18
     65                         },
     66                         {
     67                             "name": "妞妞",
     68                             "sex": "1",
     69                             "age": 21
     70                         }
     71                     ]
     72                 };
     73         
     74         //注册一个Handlebars模版,通过id找到某一个模版,获取模版的html框架
     75         //$("#table-template").html()是jquery的语法,不懂的童鞋请恶补。。。
     76         var myTemplate = Handlebars.compile($("#table-template").html());
     77         
     78         //注册一个比较大小的Helper,判断v1是否大于v2
     79         Handlebars.registerHelper("compare",function(v1,v2,options){
     80           if(v1>v2){
     81             //满足添加继续执行
     82             return options.fn(this);
     83           }else{
     84             //不满足条件执行{{else}}部分
     85             return options.inverse(this);
     86           }
     87         });
     88         
     89         //注册一个翻译用的Helper,0翻译成男,1翻译成女
     90         Handlebars.registerHelper("transformat",function(value){
     91           if(value==0){
     92             return "";
     93           }else if(value==1){
     94             return "";
     95           }
     96         });
     97         
     98         //将json对象用刚刚注册的Handlebars模版封装,得到最终的html,插入到基础table中。
     99         $('#tableList').html(myTemplate(data));
    100       });
    101     </script>
    102   </body>
    103 </html>

      小菜刚刚提到过,带options参数的Helper是块级别的,而不带的,相当于行内级别的Helper。

           从例子一开始,性别就是用0、1代码表示的,但实际情况下我们需要转换成汉字,transformat这个Helper需要一个参数,根据不同的代码,返回男女,这样调用{{transformat sex}},其中sex是从当前上下文中读取的性别代码。

    十三、关于HTML编码

     1 <!DOCTYPE html>
     2 <html>
     3   <head>
     4     <META http-equiv=Content-Type content="text/html; charset=utf-8">
     5     <title>关于HTML编码 - by 杨元</title>
     6   </head>
     7   <body>
     8     <h1>关于HTML编码</h1>
     9     <!--基础html框架-->
    10     <table>
    11       <thead>
    12         <tr>
    13           <th>姓名</th>
    14           <th>性别</th>
    15           <th>年龄</th>
    16           <th>个人主页</th>
    17         </tr>
    18       </thead>
    19       <tbody id="tableList">
    20         
    21       </tbody>
    22     </table>
    23     
    24     <!--插件引用-->
    25     <script type="text/javascript" src="script/jquery.js"></script>
    26     <script type="text/javascript" src="script/handlebars-1.0.0.beta.6.js"></script>
    27     
    28     <!--Handlebars.js模版-->
    29     <!--Handlebars.js模版放在script标签中,保留了html原有层次结构,模版中要写一些操作语句-->
    30     <!--id可以用来唯一确定一个模版,type是模版固定的写法-->
    31     <script id="table-template" type="text/x-handlebars-template">
    32       {{#each student}}
    33         <tr>
    34           <td>{{name}}</td>
    35           <td>{{sex}}</td>
    36           <td>{{age}}</td>
    37           {{#compare age 20}}
    38             <td>{{homePage}}</td>
    39           {{else}}
    40             <td>{{{homePage}}}</td>
    41           {{/compare}}
    42         </tr> 
    43       {{/each}}
    44     </script>
    45     
    46     <!--进行数据处理、html构造-->
    47     <script type="text/javascript">
    48       $(document).ready(function() {
    49         //模拟的json对象
    50         var data = {
    51                     "student": [
    52                         {
    53                             "name": "张三",
    54                             "sex": "0",
    55                             "age": 18,
    56                             "homePage":"<a href='javascript:void(0);'>张三的个人主页</a>"
    57                         },
    58                         {
    59                             "name": "李四",
    60                             "sex": "0",
    61                             "age": 22,
    62                             "homePage":"<a href='javascript:void(0);'>李四的个人主页</a>"
    63                         },
    64                         {
    65                             "name": "妞妞",
    66                             "sex": "1",
    67                             "age": 19,
    68                             "homePage":"<a href='javascript:void(0);'>妞妞的个人主页</a>"
    69                         }
    70                     ]
    71                 };
    72         
    73         //注册一个Handlebars模版,通过id找到某一个模版,获取模版的html框架
    74         //$("#table-template").html()是jquery的语法,不懂的童鞋请恶补。。。
    75         var myTemplate = Handlebars.compile($("#table-template").html());
    76         
    77         //注册一个比较数字大小的Helper,有options参数,块级Helper
    78         Handlebars.registerHelper("compare",function(v1,v2,options){
    79           //判断v1是否比v2大
    80           if(v1>v2){
    81             //继续执行
    82             return options.fn(this);
    83           }else{
    84             //执行else部分
    85             return options.inverse(this);
    86           }
    87         });
    88         
    89         //将json对象用刚刚注册的Handlebars模版封装,得到最终的html,插入到基础table中。
    90         $('#tableList').html(myTemplate(data));
    91       });
    92     </script>
    93   </body>
    94 </html>

         通过{{}}取出来的内容,都会经过编码,也就是说,如果取出的内容中包含html标签,会被转码成纯文本,不会被当成html解析,实际上就是做了类似这样的操作:把<用&lt;替代。

         这样做是很好的,既可以显示html代码,又可以避免xss注入。这个功能在做代码展示的时候是非常有用的。

         但是有时候我们可能需要解析html,不要转码,很简单,把{{}}换成{{{}}}就可以啦。

         本例中,年龄大于20的童鞋个人主页被编码,直接展示出来;而年龄小于20的童鞋,个人主页被当成html解析,显示的是一个超链接。

    十四、结束语

         有了这些功能,[ajax+json+Handlebars]替代[vo+el表达式]不成问题,新时代的曙光已经来临,最佳解决方案在此,您还等什么?

         教程到此结束。。。祝读者学习愉快。。。

    转:http://www.cnblogs.com/iyangyuan/p/3471379.html

  • 相关阅读:
    centos 给终端设快捷键
    centos 给鼠标右击添加 “打开终端” 菜单项
    centos 6.X 安装输入法
    centos U盘安装
    js的构造函数
    onresize的定义方式
    两个时间对比
    AMD和CMD的区别
    spring加载配置文件
    cglib代理
  • 原文地址:https://www.cnblogs.com/couxiaozi1983/p/4122530.html
Copyright © 2011-2022 走看看