分享

Handlebars模板引擎介绍和开发指南

 集微笔记 2014-05-16

本文翻译和整理自Handlebars Github官网,当前handlebar版本1.3.0。

介绍

Handlebars是一个Javascript模板引擎,能让你轻松高效的编写语义化模板,它是Mustache模板引擎的一个扩展,Handlebars和Mustache都是弱逻辑的模板引擎,能将Web前端的视图和代码分离,降低两者之间耦合。

Handlebars的特点是一切都是表达式,没有data api,不污染HTML标签,和DeDecms、wordpress模板类似,因此能很方便的与其他前端JS库混用,并且编写简单,易于扩展。

Handlebars支持的浏览器及运行环境有:IE6+、Chrome、Firefox、Safari5+、Opera11+以及Node.js。

Handlebars是ember.js的默认模板引擎,同时也是nodejs web框架Clouda、Meteor的默认模板引擎。

安装

Handlebars的安装很简单,你可以从 Github官网 下载最新版本,也可以从bower包管理器中将它添加到你的页面上。

用法

简单来说,Handlebars里的语法是Mustache的超集,如果你想了解基础的语法,可以查看Mustache的帮助页面,下面也将讲解Handlebars中的语法。

基础语法

Handlebars模板看起来和一般的HTML没什么两样,只不过是在HTML中嵌入了Handlebars的表达式。如下:

  1. <div class="entry"> 
  2.     <h1>{{title}}</h1> 
  3.     <div class="body"> 
  4.           {{body}} 
  5.     </div> 
  6. </div> 

一个Handlebars的表达式是被{{}}包含起来的内容。了解更多Handlebars表达式

你可以将模板的内容或数据放到一个<script>标签里,也可以直接写在javascript里:

  1. <script id="entry-template" type="text/x-handlebars-template"> 
  2. template content 
  3. </script> 

当你写了一个模板以后,使用Handlebars.compile方法将模板编译为函数,生成的执行函数接受context作为参数,用来渲染模板。了解更多执行函数

比如下面:

  1. var source = "<p>Hello, my name is {{name}}. I am from {{hometown}}. I have " + 
  2. "{{kids.length}} kids:</p>" + 
  3. "<ul>{{#kids}}<li>{{name}} is {{age}}</li>{{/kids}}</ul>"; 
  4. var template = Handlebars.compile(source); 
  5.  
  6. var data = { "name": "Alan", "hometown": "Somewhere, TX", 
  7. "kids": [{"name": "Jimmy", "age": "12"}, {"name": "Sally", "age": "4"}]}; 
  8. var result = template(data); 
  9.  
  10. // 将被渲染为: 
  11. // <p>Hello, my name is Alan. I am from Somewhere, TX. I have 2 kids:</p> 
  12. // <ul> 
  13. //   <li>Jimmy is 12</li> 
  14. //   <li>Sally is 4</li> 
  15. // </ul> 

你还可以预编译你的模板,它将会生成一个小一些的运行库,这对移动设备上的web页面非常重要。了解更多预编译

HTML转义

为安全起见,Handlebars表达式中的一些HTML字符将被转义,如果你不想让Handlebars转义字符,使用三个花括号{{{

  1. //template:  
  2.  
  3. <div class="entry"> 
  4.     <h1>{{title}}</h1> 
  5.     <div class="body"> 
  6.         {{{body}}} 
  7.     </div> 
  8. </div> 
  9.  
  10. //context: 
  11.  
  12.     title: "All about <p> Tags", 
  13.     body: "<p>This is a post about <p> tags</p>" 
  14.  
  15. //results: 
  16.  
  17. <div class="entry"> 
  18.     <h1>All About <p> Tags</h1> 
  19.     <div class="body"> 
  20.       <p>This is a post about <p> tags</p> 
  21.     </div> 
  22. </div> 

Handlebars不会转义Handlebars.SafeString,如果你想写一个输出自身HTML的helper,你可以使用这个方法,用来手动的输出需要转义的参数。

  1. Handlebars.registerHelper('link', function(text, url) { 
  2.   text = Handlebars.Utils.escapeExpression(text); 
  3.   url  = Handlebars.Utils.escapeExpression(url); 
  4.  
  5.   var result = '<a href="' + url + '">' + text + '</a>'; 
  6.  
  7.   return new Handlebars.SafeString(result); 
  8. }); 

块级表达式

块级表达式能让你定义块级helpers,它能调用模板的一部分,并且使用与当前不同的上下文。下面以一个输出HTML列表的helper为例:

{{#list people}}{{firstName}} {{lastName}}{{/list}}

定义如下的上下文:

  1.   people: [ 
  2.     {firstName: "Yehuda", lastName: "Katz"}, 
  3.     {firstName: "Carl", lastName: "Lerche"}, 
  4.     {firstName: "Alan", lastName: "Johnson"} 
  5.   ] 

我们可以创建一个名为list的helper来生成HTML列表,这个helper接受people和options参数,options包含fn属性,可以调用上下文。

  1. Handlebars.registerHelper('list', function(items, options) { 
  2.   var out = "<ul>"; 
  3.  
  4.   for(var i=0, l=items.length; i<l; i++) { 
  5.     out = out + "<li>" + options.fn(items[i]) + "</li>"; 
  6.   } 
  7.  
  8.   return out + "</ul>"; 
  9. }); 

执行后,生成:

  1. <ul> 
  2.   <li>Yehuda Katz</li> 
  3.   <li>Carl Lerche</li> 
  4.   <li>Alan Johnson</li> 
  5. </ul> 

块级helper包含更多的特性,如创建一个else部分(在内建的if helper里有用到)。

当调用options.fn(context)时内部的内容已经被转义,因此Handlebars不会转义块级helper的结果,否则会出现两次转义。了解更多块级helper

Handlebars路径

和Mustache一样,Handlebars支持简单的路径。

Handlebars还支持嵌套的路径,可以在当前上下文中寻找嵌套的属性。

  1. <div class="entry"> 
  2.   <h1>{{title}}</h1> 
  3.   <h2>By {{author.name}}</h2> 
  4.  
  5.   <div class="body"> 
  6.     {{body}} 
  7.   </div> 
  8. </div> 

其对应的上下文如下:

  1. var context = { 
  2.   title: "My First Blog Post!", 
  3.   author: { 
  4.     id: 47, 
  5.     name: "Yehuda Katz" 
  6.   }, 
  7.   body: "My first post. Wheeeee!" 
  8. }; 

因此Handlebars模板能支持更多原始的JSON对象。

嵌套的handlebars路径可以包含../字符段,可以将路径定位到父级上下文中。

  1. <h1>Comments</h1> 
  2.  
  3. <div id="comments"> 
  4.   {{#each comments}} 
  5.   <h2><a href="/posts/{{../permalink}}#{{id}}">{{title}}</a></h2> 
  6.   <div>{{body}}</div> 
  7.   {{/each}} 
  8. </div> 

在这个例子中,post是comments的父级上下文,虽然a标签处于comments的上下文里,但permalink可以上溯到post上下文中。

更严密的讲,../路径指的是父级模板的作用域,而不是高一级的上下文,这是因为块级helper能调用任何上下文,所以“上一级”的概念在这里并不适合。

模板注释

在handlebars中使用{{! }}或者{{!-- --}}来包含注释。

  1. <div class="entry"> 
  2.   {{! only output this author names if an author exists }} 
  3.   {{#if author}} 
  4.     <h1>{{firstName}} {{lastName}}</h1> 
  5.   {{/if}} 
  6. </div> 

Helpers(辅助方法)

Helpers是Handlebars中最重要的概念,它能大大扩展Handlebars的使用范围,Helper自定义函数的形式将所需要的功能注册为表达式,然后可以在Handlebars中使用。

Handlebars提供了Handlebars.registerHelper方法来自定义Helper,同时也提供了一些常用的内建Helper。

比如有如下模板:

  1. <div class="post"> 
  2.   <h1>By {{fullName author}}</h1> 
  3.   <div class="body">{{body}}</div> 
  4.  
  5.   <h1>Comments</h1> 
  6.  
  7.   {{#each comments}} 
  8.   <h2>By {{fullName author}}</h2> 
  9.   <div class="body">{{body}}</div> 
  10.   {{/each}} 
  11. </div> 

其中上下文和helper如下:

  1. var context = { 
  2.   author: {firstName: "Alan", lastName: "Johnson"}, 
  3.   body: "I Love Handlebars", 
  4.   comments: [{ 
  5.     author: {firstName: "Yehuda", lastName: "Katz"}, 
  6.     body: "Me too!" 
  7.   }] 
  8. }; 
  9.  
  10. Handlebars.registerHelper('fullName', function(person) { 
  11.   return person.firstName + " " + person.lastName; 
  12. }); 

运行结果:

  1. <div class="post"> 
  2.   <h1>By Alan Johnson</h1> 
  3.   <div class="body">I Love Handlebars</div> 
  4.  
  5.   <h1>Comments</h1> 
  6.  
  7.   <h2>By Yehuda Katz</h2> 
  8.   <div class="body">Me Too!</div> 
  9. </div> 

Helpers还可以接受块级元素当前的上下文,就像函数中的this上下文一样。

  1. <ul> 
  2.   {{#each items}} 
  3.   <li>{{agree_button}}</li> 
  4.   {{/each}} 
  5. </ul> 

上下文及helper如下:

  1. var context = { 
  2.   items: [ 
  3.     {name: "Handlebars", emotion: "love"}, 
  4.     {name: "Mustache", emotion: "enjoy"}, 
  5.     {name: "Ember", emotion: "want to learn"} 
  6.   ] 
  7. }; 
  8.  
  9. Handlebars.registerHelper('agree_button', function() { 
  10.   return new Handlebars.SafeString( 
  11.     "<button>I agree. I " + this.emotion + " " + this.name + "</button>" 
  12.   ); 
  13. }); 

运行结果:

  1. <ul> 
  2.   <li><button>I agree. I love Handlebars</button></li> 
  3.   <li><button>I agree. I enjoy Mustache</button></li> 
  4.   <li><button>I agree. I want to learn Ember</button></li> 
  5. </ul> 

内建Helpers

Handlebars提供了一系列的内建Helper供直接调用。

with:切换上下文

each:循环输出上下文中的内容,用this表达式指代单条内容,else表达式当上下文为空时激活

if:条件表达式

unless:与if表达式功能相反

log:输出log本文翻译和整理自Handlebars Github官网,当前handlebar版本1.3.0。

介绍

Handlebars是一个Javascript模板引擎,能让你轻松高效的编写语义化模板,它是Mustache模板引擎的一个扩展,Handlebars和Mustache都是弱逻辑的模板引擎,能将Web前端的视图和代码分离,降低两者之间耦合。

Handlebars的特点是一切都是表达式,没有data api,不污染HTML标签,和DeDecms、wordpress模板类似,因此能很方便的与其他前端JS库混用,并且编写简单,易于扩展。

Handlebars支持的浏览器及运行环境有:IE6+、Chrome、Firefox、Safari5+、Opera11+以及Node.js。

Handlebars是ember.js的默认模板引擎,同时也是nodejs web框架Clouda、Meteor的默认模板引擎。

安装

Handlebars的安装很简单,你可以从 Github官网 下载最新版本,也可以从bower包管理器中将它添加到你的页面上。

用法

简单来说,Handlebars里的语法是Mustache的超集,如果你想了解基础的语法,可以查看Mustache的帮助页面,下面也将讲解Handlebars中的语法。

基础语法

Handlebars模板看起来和一般的HTML没什么两样,只不过是在HTML中嵌入了Handlebars的表达式。如下:

  1. <div class="entry"> 
  2.     <h1>{{title}}</h1> 
  3.     <div class="body"> 
  4.           {{body}} 
  5.     </div> 
  6. </div> 

一个Handlebars的表达式是被{{}}包含起来的内容。了解更多Handlebars表达式

你可以将模板的内容或数据放到一个<script>标签里,也可以直接写在javascript里:

  1. <script id="entry-template" type="text/x-handlebars-template"> 
  2. template content 
  3. </script> 

当你写了一个模板以后,使用Handlebars.compile方法将模板编译为函数,生成的执行函数接受context作为参数,用来渲染模板。了解更多执行函数

比如下面:

  1. var source = "<p>Hello, my name is {{name}}. I am from {{hometown}}. I have " + 
  2. "{{kids.length}} kids:</p>" + 
  3. "<ul>{{#kids}}<li>{{name}} is {{age}}</li>{{/kids}}</ul>"; 
  4. var template = Handlebars.compile(source); 
  5.  
  6. var data = { "name": "Alan", "hometown": "Somewhere, TX", 
  7. "kids": [{"name": "Jimmy", "age": "12"}, {"name": "Sally", "age": "4"}]}; 
  8. var result = template(data); 
  9.  
  10. // 将被渲染为: 
  11. // <p>Hello, my name is Alan. I am from Somewhere, TX. I have 2 kids:</p> 
  12. // <ul> 
  13. //   <li>Jimmy is 12</li> 
  14. //   <li>Sally is 4</li> 
  15. // </ul> 

你还可以预编译你的模板,它将会生成一个小一些的运行库,这对移动设备上的web页面非常重要。了解更多预编译

HTML转义

为安全起见,Handlebars表达式中的一些HTML字符将被转义,如果你不想让Handlebars转义字符,使用三个花括号{{{

  1. //template:  
  2.  
  3. <div class="entry"> 
  4.     <h1>{{title}}</h1> 
  5.     <div class="body"> 
  6.         {{{body}}} 
  7.     </div> 
  8. </div> 
  9.  
  10. //context: 
  11.  
  12.     title: "All about <p> Tags", 
  13.     body: "<p>This is a post about <p> tags</p>" 
  14.  
  15. //results: 
  16.  
  17. <div class="entry"> 
  18.     <h1>All About <p> Tags</h1> 
  19.     <div class="body"> 
  20.       <p>This is a post about <p> tags</p> 
  21.     </div> 
  22. </div> 

Handlebars不会转义Handlebars.SafeString,如果你想写一个输出自身HTML的helper,你可以使用这个方法,用来手动的输出需要转义的参数。

  1. Handlebars.registerHelper('link', function(text, url) { 
  2.   text = Handlebars.Utils.escapeExpression(text); 
  3.   url  = Handlebars.Utils.escapeExpression(url); 
  4.  
  5.   var result = '<a href="' + url + '">' + text + '</a>'; 
  6.  
  7.   return new Handlebars.SafeString(result); 
  8. }); 

块级表达式

块级表达式能让你定义块级helpers,它能调用模板的一部分,并且使用与当前不同的上下文。下面以一个输出HTML列表的helper为例:

{{#list people}}{{firstName}} {{lastName}}{{/list}}

定义如下的上下文:

  1.   people: [ 
  2.     {firstName: "Yehuda", lastName: "Katz"}, 
  3.     {firstName: "Carl", lastName: "Lerche"}, 
  4.     {firstName: "Alan", lastName: "Johnson"} 
  5.   ] 

我们可以创建一个名为list的helper来生成HTML列表,这个helper接受people和options参数,options包含fn属性,可以调用上下文。

  1. Handlebars.registerHelper('list', function(items, options) { 
  2.   var out = "<ul>"; 
  3.  
  4.   for(var i=0, l=items.length; i<l; i++) { 
  5.     out = out + "<li>" + options.fn(items[i]) + "</li>"; 
  6.   } 
  7.  
  8.   return out + "</ul>"; 
  9. }); 

执行后,生成:

  1. <ul> 
  2.   <li>Yehuda Katz</li> 
  3.   <li>Carl Lerche</li> 
  4.   <li>Alan Johnson</li> 
  5. </ul> 

块级helper包含更多的特性,如创建一个else部分(在内建的if helper里有用到)。

当调用options.fn(context)时内部的内容已经被转义,因此Handlebars不会转义块级helper的结果,否则会出现两次转义。了解更多块级helper

Handlebars路径

和Mustache一样,Handlebars支持简单的路径。

Handlebars还支持嵌套的路径,可以在当前上下文中寻找嵌套的属性。

  1. <div class="entry"> 
  2.   <h1>{{title}}</h1> 
  3.   <h2>By {{author.name}}</h2> 
  4.  
  5.   <div class="body"> 
  6.     {{body}} 
  7.   </div> 
  8. </div> 

其对应的上下文如下:

  1. var context = { 
  2.   title: "My First Blog Post!", 
  3.   author: { 
  4.     id: 47, 
  5.     name: "Yehuda Katz" 
  6.   }, 
  7.   body: "My first post. Wheeeee!" 
  8. }; 

因此Handlebars模板能支持更多原始的JSON对象。

嵌套的handlebars路径可以包含../字符段,可以将路径定位到父级上下文中。

  1. <h1>Comments</h1> 
  2.  
  3. <div id="comments"> 
  4.   {{#each comments}} 
  5.   <h2><a href="/posts/{{../permalink}}#{{id}}">{{title}}</a></h2> 
  6.   <div>{{body}}</div> 
  7.   {{/each}} 
  8. </div> 

在这个例子中,post是comments的父级上下文,虽然a标签处于comments的上下文里,但permalink可以上溯到post上下文中。

更严密的讲,../路径指的是父级模板的作用域,而不是高一级的上下文,这是因为块级helper能调用任何上下文,所以“上一级”的概念在这里并不适合。

模板注释

在handlebars中使用{{! }}或者{{!-- --}}来包含注释。

  1. <div class="entry"> 
  2.   {{! only output this author names if an author exists }} 
  3.   {{#if author}} 
  4.     <h1>{{firstName}} {{lastName}}</h1> 
  5.   {{/if}} 
  6. </div> 

Helpers(辅助方法)

Helpers是Handlebars中最重要的概念,它能大大扩展Handlebars的使用范围,Helper自定义函数的形式将所需要的功能注册为表达式,然后可以在Handlebars中使用。

Handlebars提供了Handlebars.registerHelper方法来自定义Helper,同时也提供了一些常用的内建Helper。

比如有如下模板:

  1. <div class="post"> 
  2.   <h1>By {{fullName author}}</h1> 
  3.   <div class="body">{{body}}</div> 
  4.  
  5.   <h1>Comments</h1> 
  6.  
  7.   {{#each comments}} 
  8.   <h2>By {{fullName author}}</h2> 
  9.   <div class="body">{{body}}</div> 
  10.   {{/each}} 
  11. </div> 

其中上下文和helper如下:

  1. var context = { 
  2.   author: {firstName: "Alan", lastName: "Johnson"}, 
  3.   body: "I Love Handlebars", 
  4.   comments: [{ 
  5.     author: {firstName: "Yehuda", lastName: "Katz"}, 
  6.     body: "Me too!" 
  7.   }] 
  8. }; 
  9.  
  10. Handlebars.registerHelper('fullName', function(person) { 
  11.   return person.firstName + " " + person.lastName; 
  12. }); 

运行结果:

  1. <div class="post"> 
  2.   <h1>By Alan Johnson</h1> 
  3.   <div class="body">I Love Handlebars</div> 
  4.  
  5.   <h1>Comments</h1> 
  6.  
  7.   <h2>By Yehuda Katz</h2> 
  8.   <div class="body">Me Too!</div> 
  9. </div> 

Helpers还可以接受块级元素当前的上下文,就像函数中的this上下文一样。

  1. <ul> 
  2.   {{#each items}} 
  3.   <li>{{agree_button}}</li> 
  4.   {{/each}} 
  5. </ul> 

上下文及helper如下:

  1. var context = { 
  2.   items: [ 
  3.     {name: "Handlebars", emotion: "love"}, 
  4.     {name: "Mustache", emotion: "enjoy"}, 
  5.     {name: "Ember", emotion: "want to learn"} 
  6.   ] 
  7. }; 
  8.  
  9. Handlebars.registerHelper('agree_button', function() { 
  10.   return new Handlebars.SafeString( 
  11.     "<button>I agree. I " + this.emotion + " " + this.name + "</button>" 
  12.   ); 
  13. }); 

运行结果:

  1. <ul> 
  2.   <li><button>I agree. I love Handlebars</button></li> 
  3.   <li><button>I agree. I enjoy Mustache</button></li> 
  4.   <li><button>I agree. I want to learn Ember</button></li> 
  5. </ul> 

内建Helpers

Handlebars提供了一系列的内建Helper供直接调用。

with:切换上下文

each:循环输出上下文中的内容,用this表达式指代单条内容,else表达式当上下文为空时激活

if:条件表达式

unless:与if表达式功能相反

log:输出log

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多