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.


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM