Handlebars.js,Json+ajax+拼html

中  {{  和  }}  之间为handlerbars的变量;
<div class="entry"><h1>{{title}}</h1> <div class="body">{{body}}</div></div>
把数据放到自己定义的 <script> 标签中;
<script  id="entry-template" type="text/x-handlebars-template">  template content</script>

编译模版

使用 Handlebars.compile() 进行编译模版;
var source   =$("#entry-template").html();
var template = Handlebars.compile(source);
智能编译模版(在移动端也能运行哦么么哒)

生成html代码

通过上面的模版和数据混合编译后的结果:
var context = {title: "标题", body: "我是字符串!"}
var html    = template(context);
<body>
<script src="http://libs.baidu.com/jquery/1.9.0/jquery.js"></script>
<script src="http://cdn.madebyglutard.com/libs/handlebars.js/2.0.0/handlebars.js"></script>
<div id="div1"></div>
<script id="entry-template" type="text/x-handlebars-template">
{{!在js中写html模板}}
<div class="entry">
    <h1>{{title}}</h1>
    <div class="body">
        {{body}}
</div>
</div>
</script>
<script>//JS代码    
 var source   = $("#entry-template").html();
var template = Handlebars.compile(source);
    var context = {title: "标题", body: "我是字符串!"} //数据信息
    var html    =template(context);
    document.getElementById("div1").innerHTML= html;
//jQuery中 html(),插入到div1

</script> </body>
---------------------------------------------
//模版的代码和JS的代码如防止HTML被转义的方法;
{{ }}和 {{{}}}和区别就是, 如果你不希望变量里面的字符串被转义就使用{{{ }}}对变量进行处理;//可能以因为body等是html标签,避免将变量误认为特殊关键字,需要{{{ }}}
Handlebars的 {{expression}} 表达式会返回一个 HTML编码 HTML-escape 过的值。如果不希望Handlebars来编码这些值,使用三个大括号即可:{{{
<div class="entry">
  <h1>{{title}}</h1>
  <div class="body"> {{{body}}}  </div>
</div>
数据如下:
{
  title: "All about <p> Tags",
  body: "<p>This is a post about &lt;p&gt; tags</p>"
}
Handlebars 不会再对 Handlebars.SafeString 安全字符串进行编码。如果你写的 helper 用来生成 HTML,就经常需要返回一个 new Handlebars.SafeString(result)。在这种情况下,你就需要手动的来编码参数了。
定义的Helper如下:
Handlebars.registerHelper('link', function(text, url) {
      text = Handlebars.Utils.escapeExpression(text);
      url  = Handlebars.Utils.escapeExpression(url);   
    var result ='<a href="'+ url +'">'+ text +'</a>';  //手动编码是指这句?  return new Handlebars.SafeString(result);
    });
    
这样来编码传递进来的参数,并把返回的值标记为 安全,这样的话,即便不是哟给你“三个大括号”,Handlebars 就不会再次编码它了。
渲染以后的结果如下:
&lt; < , little to
&gt; >, greater to
<div class="entry">
 <h1>All About &lt;p&gt; Tags</h1>
 <div class="body"><p>This is a post about &lt;p&gt; tags</p></div>
</div>
//代码如下:
<body>
<script src="http://libs.baidu.com/jquery/1.9.0/jquery.js"></script>
<script src="http://cdn.madebyglutard.com/libs/handlebars.js/2.0.0/handlebars.js"></script>
<div id="div2"></div>
<script id="entry-template1" type="text/x-handlebars-template">
  <div class="entry">
      <h1>{{title}}</h1>
      <div class="body">
        {{{body}}}
      </div>
  </div>
</script>
<script>
    Handlebars.registerHelper('link', function(text, url) {
      text =Handlebars.Utils.escapeExpression(text);
      url  = Handlebars.Utils.escapeExpression(url);
      var result ='<a href="'+ url +'">'+ text +'</a>';
    
      return new Handlebars.SafeString(result);
    });
    var source   = $("#entry-template1").html();
    var template = Handlebars.compile(source);
    var context = {
      title: "All about <p> Tags",
      body: "<p>This is a post about &lt;p&gt; tags</p>"
    };
    var html    = template(context);
    document.getElementById("div2").innerHTML = html;
</script>
</body>
-------------------------------------------------------------
Handlerbars的自定义表达式

块级表达式:#开头,/结尾。
块级表达式允许你定义一个helpers,并使用一个不同于当前的上下文(context)来调用你模板的一部分。现在考虑下这种情况,你需要一个helper来生成一段 HTML 列表:

{{#list people}}
   {{firstName}}
   {{lastName}}
{{/list}} 
并使用下面的上下文(数据):
{
  people: [
    {firstName: "Yehuda", lastName: "Katz"},
    {firstName: "Carl", lastName: "Lerche"},
    {firstName: "Alan", lastName: "Johnson"}
  ]
}
此时需要创建一个 名为 list 的 helper 来生成这段 HTML 列表。这个 helper 使用people 作为第一个参数,还有一个 options 对象(hash哈希)作为第二个参数。这个 options 对象有一个叫 fn 的属性,你可以传递一个上下文给它(fn),就跟执行一个普通的 Handlebars 模板一样:
在JS里面定义这个helper;
Handlebars.registerHelper('list', function(items, options) {
  var out ="<ul>";
  for(var i=0, l=items.length; i<l; i++) {
     out = out +"<li>"+ options.fn(items[i]) +"</li> " ;       /*options.fn相当于一个编译的函数*/
  }  

  return out +"</ul>";
});
执行以后的结果是:
<ul><li>Yehuda Katz</li><li>Carl Lerche</li><li>Alan Johnson</li></ul>
自定义块表达式还有很多别的特性, 比如可以直接使用 IF 和 ELSE;
//代码如下:
<body>
<script src="http://libs.baidu.com/jquery/1.9.0/jquery.js"></script>
<script src="http://cdn.madebyglutard.com/libs/handlebars.js/2.0.0/handlebars.js"></script>

<div id="div3"></div>

<script id="entry-template2" type="text/x-handlebars-template">    
    {{! 这个是模版的注释,
people
对应数据中的people[] }} {{#list people}} {{firstName}} {{lastName}} {{/list}} </script> <script> Handlebars.registerHelper('list', function(items, options) { var out ="<ul>"; for(var i=0, l=items.length; i<l; i++) { out = out +"<li>"+ options.fn(items[i]) +"</li>"; /*options.fn相当于一个编译的函数*/ } return out +"</ul>"; }); var source = $("#entry-template2").html(); var template = Handlebars.compile(source); var context = {  people: [ {firstName: "Yehuda", lastName: "Katz"}, {firstName: "Carl", lastName: "Lerche"}, {firstName: "Alan", lastName: "Johnson"}  ] }; var html = template(context); document.getElementById("div3").innerHTML= html; //jQuery中 html()</script></body>

块级的 helpers 还有很多其他的特性,比如可以创建一个 else 区块(例如,内置的 if helper 就是用 else)。
注意,因为在你执行 options.fn(context) 的时候,这个 helper 已经把内容编码一次了,所以 Handlebars 不会再对这个 helper 输出的值进行编码了。如果编码了,这些内容就会被编码两 次!

Handlebars次级数据的渲染(Handlebars 路径)

Handlebars支持简单的下级对象获取和上级对象获取, 跟 Mustache一样样的.
<p>{{name}}</p>
Handlebars 同样也支持嵌套的路径,这样的话就可以在当前的上下文中查找内部嵌套的属性了。
<div  class="entry">
  <h1>{{title}}</h1>
  <h2>By {{author.name}}</h2>
  <div class="body">{{body}}</div>
</div>
上面的模板使用下面这段上下文:
这样一来 Handlebars 就可以直接把JSON数据拿来用了。
var context = {
  title: "My First Blog Post!",
 author: {
    id: 47,
    name:"Yehuda Katz"},
  body: "My first post. Wheeeee!"
};
<body>
<script src="http://libs.baidu.com/jquery/1.9.0/jquery.js"></script>
<script src="http://cdn.madebyglutard.com/libs/handlebars.js/2.0.0/handlebars.js"></script>

<div id="div4"></div>

<script id="entry-template3" type="text/x-handlebars-template">
<div class="entry">
   <h1>{{title}}</h1>
   <h2>By {{author.name}}</h2>gg
   <div class="body">
        {{body}}
   </div>
</div>
</script>
<script>
    var source   = $("#entry-template3").html();
    var template = Handlebars.compile(source);
    var context = {
      title: "My First Blog Post!",
      author: {
        id: 47,
        name: "Yehuda Katz"
      },
      body: "My first post. Wheeeee!"
    };
    var html    = template(context);
    document.getElementById("div4").innerHTML = html;
</script>
</body>
-------------------------
Handlebars 可以迭代Object对象(纯对象或者数组); 在模版中的../是对象的父级;
<h1>Comments</h1>
<div id="comments">
{{#each comments}}
  <h2><a href="/posts/{{../permalink}}#{{id}}"> {{title}} </a></h2>
  <div>{{body}}< div>
{{/each}}
</div>
尽管 a 链接在输出时是以 comment 评论为上下文的,但它仍然可以退回上一层的上下文(post上下文)并取出permalink(固定链接)值。
var context = {
  post: {
    body:'这是文章内容',
    permalink: 'http://xx.com/xx',
    comments:[{
      title:'这篇文章不错,赞一个'
    },{
      title:'好文要顶!'
    }]
  }
}
../ 标识符表示对模板的父级作用域的引用,并不表示在上下文数据中的上一层。这是因为块级 helpers 可以以任何上下文来调用一个块级表达式,所以这个【上一层】的概念用来指模板作用域的父级更有意义些。
The exact value that ../ will resolve to varies based on the helper that is calling the block. Using ../ is only necessary when context changes, so children of helpers such as each would require the use of ../while children of helpers such as if do not.
{{permalink}}
{{#each comments}}
  {{../permalink}}
  {{#if title}}
      {{../permalink}}
  {{/if}}
{{/each}}
In this example all of the above reference the same permalink value even though they are located within different blocks. This behavior is new as of Handlebars 4, the release notes discuss the prior behavior as well as the migration plan.
Handlebars也允许通过一个 this 的引用来解决 helpers 和 数据字段间的名字冲突
 
下面展示的name都是同样的东西;
<p>{{./name}} or {{this/name}} or {{this.name}}</p>

上面的这一种方式都会将 name 字段引用到当前上下文上,而不是 helper 上的同名属性。

-----------------------------------------------------

注释: {{!-- --}} 或者{{! }}或者 <!-- -->.

可以把模版专用的注释写在模版文件里面么么哒. 提高代码的可读性, 这个也算是最佳实践吧;
<divclass="entry">
{{!-- only output this author names if an author exists --}}
{{#if author}}<h1>{{firstName}}{{lastName}}</h1>{{/if}}
</div>
{{!-- --}}和{{! }}的注释不会出现在生成的代码中; 如果使用 <!-- --> 注释的代码会出现在生成的代码中;

------------------------------------------------------

自定义标签(Helpers)

Handlebars 的 helpers 在模板中可以访问任何的上下文。可以通过Handlebars.registerHelper 方法注册一个 helper。
<div class="post">
<h1>By {{fullName author}}</h1>
<div class="body">{{body}}</div>
<h1>Comments</h1>
{{#each comments}}<
  h2>By {{fullName author}}</h2><divclass="body">{{body}}</div>
{{/each}}
</div>
用下面的上下文数据和 helpers:
var context = {
  author: {firstName: "Alan", lastName: "Johnson"},
  body: "I Love Handlebars",
  comments: [{
    author: {firstName: "Yehuda", lastName: "Katz"},
    body: "Me too!"
  }]
};

//就是下面这个helper提供了模版中的自定义标签;
Handlebars.registerHelper('fullName', function(person) {
  return person.firstName +""+ person.lastName;
});
生成的结果如下:
<divclass="post">
<h1>By Alan Johnson</h1>
<divclass="body">I Love Handlebars</div>
<h1>Comments</h1>
<h2>By Yehuda Katz</h2>
<divclass="body">Me Too!</div>
</div>
代码如下:
<body>
<script src="http://libs.baidu.com/jquery/1.9.0/jquery.js"></script>
<script src="http://cdn.madebyglutard.com/libs/handlebars.js/2.0.0/handlebars.js"></script>
<div id="div5"></div>
<script id="entry-template5" type="text/x-handlebars-template">
<div class="post">
    <h1>By {{fullName author}}</h1>
    <div class="body">{{body}}</div>
    <h1>Comments</h1>    
    {{#each comments}}
        <h2>By {{fullNameauthor}}</h2> //自定义标签fullName, Handlebars.registerHelper()        <div class="body">{{body}}</div>
    {{/each}}
</div>
</script>
<script>
   var context = {
      author: {firstName: "Alan", lastName: "Johnson"},
      body: "I Love Handlebars",
      comments: [{
         author: {firstName: "Yehuda", lastName: "Katz"},
         body: "Me too!"
      }]
    };
    
    //就是下面这个helper提供了模版中的自定义标签;
    Handlebars.registerHelper('fullName', function(person) {
       return person.firstName +""+ person.lastName;
    });
    
    var source   = $("#entry-template5").html();
    vartemplate= Handlebars.compile(source);
    var html    =template(context);
    document.getElementById("div5").innerHTML = html;// .html()
</script>
</body>
-----------------------------------------
Helpers 会把当前的上下文作为函数中的 this 上下文。
在自定义标签的Helper可以使用this, this是当前的对象;
<ul>{{#each items}}<li>{{agree_button}}</li>{{/each}}</ul>
这个是填充的数据和定义的Helpers:(使用下面的 this上下文 和 helpers)
var context = {
  items: [
    {name: "Handlebars", emotion: "love"},
    {name: "Mustache", emotion: "enjoy"},
    {name: "Ember", emotion: "want to learn"}
  ]
};

Handlebars.registerHelper('agree_button', function() {
  var emotion = Handlebars.escapeExpression(this.emotion),
      name = Handlebars.escapeExpression(this.name);

  return new Handlebars.SafeString(
    "<button>I agree. I "+ emotion +""+ name +"</button>"
  );
});
生成的结果如下:
<ul><li><button>I agree. I love Handlebars</button></li><li><button>I agree. I enjoy Mustache</button></li><li><button>I agree. I want to learn Ember</button></li></ul>
如果你希望你返回的HTML代码不被转义, 就要在定义的Helper中返回 new Handlebars.SafeString; 
return new Handlebars.SafeString(代码)

自定义标签(Helpers)的更多信息;

Handlebars 提供 if 在模版中进行简单的逻辑处理; 以及迭代处理的标签 each .
//例子代码段:
<body>
<script src="http://libs.baidu.com/jquery/1.9.0/jquery.js"></script>
<script src="http://cdn.madebyglutard.com/libs/handlebars.js/2.0.0/handlebars.js"></script>
<div id="div6"></div>
<script id="entry-template6" type="text/x-handlebars-template">    
    {{#list people}}{{firstName}} {{lastName}}{{/list}}</script><script>var context = {
      people: [
        {firstName: "Yehuda", lastName: "Katz"},
        {firstName: "Carl", lastName: "Lerche"},
        {firstName: "Alan", lastName: "Johnson"}
      ]
    };
    Handlebars.registerHelper('list', function(items, options) {
      var out ="<ul>";
    
      for(var i=0, l=items.length; i<l; i++) {
        out = out +"<li>"+ options.fn(items[i]) +"</li>";
      }
    
      return out +"</ul>";
    });    
    
    var source   = $("#entry-template6").html();
    var template = Handlebars.compile(source);
    var html    = template(context);
    document.getElementById("div6").innerHTML = html;
</script>
</body>
//handlebars的IF ELSE语句和 each语句的例子:
<body>
<script src="http://libs.baidu.com/jquery/1.9.0/jquery.js"></script>
<script src="http://cdn.madebyglutard.com/libs/handlebars.js/2.0.0/handlebars.js"></script>
<div id="div7"></div>
<script id="entry-template7" type="text/x-handlebars-template">    
    {{#ifhaveIf}}我有If{{else}}我没有If{{/if}};   //if...else... 
    {{#each arr}}
        <p>{{this.a}} &gt; &gt; <span>this.data</span></p> 
    {{/each}} 
   
    {{!迭代这条对象}}
    {{#eachtest}}
        {{!如果满足条件就打印第一个模版, 如果不满足条件就打印第二个模版, helper做的只是对数据进行判断而已}}    
        {{#inverse}}
              <p>{{this.direct}}</p> 
        {{else}}  //前面的if在哪?
              <p>inverse:{{this.inverse}}</p>
        {{/inverse}}
    {{/each}}
</script>
<script>
    var context = {
        haveIf : true,
        arr : [
            { a : "a" , data : "___a"},
            { a : "b" , data : "___b"},
            { a : "c" , data : "___c"}
        ],
        test : [
            {
                condition : true,
                direct : "打印dir"
            },
            {
                condition : false,
                direct : "dir",
                inverse : "打印inverse"
            }
        ]
    };
    //自定义标签inverse
//options? Handlebars.registerHelper('inverse', function(options) { if(this.condition ) { returnoptions.fn(this); //options.fn()? }else{ returnoptions.inverse(this); } }); var source = $("#entry-template7").html(); var template = Handlebars.compile(source); var html = template(context); document.getElementById("div7").innerHTML = html; </script> </body>

内置的 Helpers

1.each helper

你可以使用内置的 each helper 来循环一个列表,循环中可以使用this 来代表当前被循环的列表项。

<ul class="people_list">
  {{#each people}}
  <li>{{this}}</li>
  {{/each}}
</ul>

使用这个上下文:

{
  people: [
    "Yehuda Katz",
    "Alan Johnson",
    "Charles Jolley"
  ]
}

会得到:

<ulclass="people_list"><li>Yehuda Katz</li><li>Alan Johnson</li><li>Charles Jolley</li></ul>

事实上,可以使用 this 表达式在任何上下文中表示对当前的上下文的引用。
还可以选择性的使用 else ,当被循环的是一个空列表的时候会显示其中的内容。

{{#each paragraphs}}
  <p>{{this}}</p>
{{else}}
  <p class="empty">No content</p>
{{/each}}

在使用 each 来循环列表的时候,可以使用 {{@index}} 来表示当前循环的索引值

{{#each array}}
  {{@index}}: {{this}}
{{/each}}

对于 object 类型的循环,可以使用 {{@key}} 来表示:

{{#each object}}
  {{@key}}: {{this}}
{{/each}}

 

--------------------------------------

2. with helper

一般情况下,Handlebars 模板在计算值时,会把传递给模板的参数作为上下文。

var source   = "<p>{{lastName}}, {{firstName}}</p>";
var template = Handlebars.compile(source);
template({firstName: "Alan", lastName: "Johnson"});

结果如下:

<p>Johnson, Alan</p>
不过也可以在模板的某个区域切换上下文,使用内置的 with helper即可。
<divclass="entry"><h1>{{title}}</h1>
  {{#with author}}
      <h2>By {{firstName}} {{lastName}}</h2>
  {{/with}}
</div>

在使用下面数据作为上下文时:

{
  title:"My first post!",
  author: {
    firstName: "Charles",
    lastName: "Jolley"}
}

会得到如下结果:

<divclass="entry"><h1>My first post!</h1><h2>By Charles Jolley</h2></div>
----------------------------

3. if helper

if 表达式可以选择性的渲染一些区块。如果它的参数返回 false,undefinednull"" 或 [](译注:还有 0)(都是JS中的“假”值),Handlebars 就不会渲染这一块内容:

<div class="entry">
  {{#if author}}
  <h1>{{firstName}} {{lastName}}</h1>
  {{/if}}
</div>

当时用一个空对象({})作为上下文时,会得到:

<div class="entry">
</div>
在使用 if 表达式的时候,可以配合 {{else}} 来使用,这样当参数返回 假 值时,可以渲染 else 区块:
<div class="entry">
  {{#if author}}
    <h1>{{firstName}} {{lastName}}</h1>
  {{else}}
    <h1>Unknown Author</h1>
  {{/if}}
</div>
4.  

unless helper

unless helper 和 if helper 是正好相反的,当表达式返回假值时就会渲染其内容:

<div class="entry">
  {{#unless license}}
  <h3 class="warning">WARNING: This entry does not have a license!</h3>
  {{/unless}}
</div>
如果在当前上下文中查找 license 返回假值,Handlebars 就会渲染这段警告信息。反之,就什么也不输出。

5.log helper

log helper 可以在执行模板的时候输出当前上下文的状态。

{{log"Look at me!"}}
这样会把委托信息发送给 Handlebars.logger.log,而且这个函数可以重写来实现自定义的log。

Literals

Helper calls may also have literal values passed to them either as parameter arguments or hash arguments. Supported literals include numbers, strings, truefalsenull and undefined.
{{agree_button "My Text"class="my-class" visible=true counter=4}}

Partials

Handlebars partials allow for code reuse by creating shared templates. Rendering this template
<divclass="post">{{> userMessage tagName="h1" }}<h1>Comments</h1>{{#each comments}}{{> userMessage tagName="h2" }}{{/each}}</div>
when using this partial and context:
Handlebars.registerPartial('userMessage',
    '<{{tagName}}>By {{author.firstName}} {{author.lastName}}</{{tagName}}>'+'<div class="body">{{body}}</div>');
var context = {
  author: {firstName: "Alan", lastName: "Johnson"},
  body: "I Love Handlebars",
  comments: [{
    author: {firstName: "Yehuda", lastName: "Katz"},
    body: "Me too!"
  }]
};
results in:
<divclass="post"><h1>By Alan Johnson</h1><divclass="body">I Love Handlebars</div><h1>Comments</h1><h2>By Yehuda Katz</h2><divclass="body">Me Too!</div></div>

Built-In Helpers

Handlebars offers a variety of built-in helpers such as the if conditional and each iterator.
Learn More: Built-In Helpers 

API Reference

Handlebars offers a variety of APIs and utility methods for applications and helpers.
原文地址:https://www.cnblogs.com/zyjzz/p/6561839.html