Handlebars 文档笔记

Handlebars 兼容 Mustache 模板

对比了几个 Node.js 常用模板,什么 EJS 、Jade 等等,还是感觉 Handlebars 比较顺手,模板只做数据展示,前端逻辑的东西通过 helper 实现,HTML 中没有掺杂太多 JS 的东西,看起来整洁一些。

Express 中引入 Handlebars 模板的话,需要引入hbs 模块

handlebars 表达式

<h1>{{title}}</h1>  

在上下文中找 title 属性,获取它的值

点分割表达式

<h1>{{article.title}}</h1>  

当前上下文找 article 属性,再找它的 title 属性

标识符可以是除了以下字符以外的 unicode 字符 Whitespace ! “ # % & ‘ ( ) * + , . / ; < = > @ [ \ ] ^ ` { | } ~

不合法的标识符用 “[]” 包装


   
   
{{#each articles.[10].[#comments]}}
<h1>{{subject}}</h1>
<div>
{{body}}
</div>
{{/each}}

不转义

{{{foo}}}

Helpers

0 或多个参数,用空格分割,每个参数是个 handlebars 表达式

{{{link story}}}

link 是 helper 名字,story 是 helper 参数。

注册 helper


   
   
Handlebars.registerHelper('link', function(object) {
return new Handlebars.SafeString(
"<a href='" + object.url + "'>" + object.text + "</a>"
);
});

helper 返回 HTML ,不想被转义,用 Handlebars.SafeString()

helper 把接收的上下文作为 this 上下文


   
   
<ul>
{{#each items}}
<li>{{agree_button}}</li>
{{/each}}
</ul>

上下文和 helper:


   
   
var context = {
items: [
{name: "Handlebars", emotion: "love"},
{name: "Mustache", emotion: "enjoy"},
{name: "Ember", emotion: "want to learn"}
]
};

   
   
Handlebars.registerHelper('agree_button', function() {
return new Handlebars.SafeString(
"<button>I agree. I " + this.emotion + " " + this.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>

也可以直接传字符串参数

{{{link "See more..." story.url}}}

等价于

{{{link story.text story.url}}}

   
   
Handlebars.registerHelper('link', function(text, url) {
return new Handlebars.SafeString(
"<a href='" + url + "'>" + text + "</a>"
);
});

helper 最后一个参数也可以接收可选的键值对序列(文档提到的 hash 参数)

{{{link "See more..." href=story.url class="story"}}}

hash 参数的 key 必须是简单的标识符,value 是 Handlebars 表达式,value 可以是简单的标识符,路径,或者字符串。


   
   
Handlebars.registerHelper('link', function(text, options) {
var attrs = [];
for(var prop in options.hash) {
attrs.push(prop + '="' + options.hash[prop] + '"');
}
return new Handlebars.SafeString(
"<a " + attrs.join(" ") + ">" + text + "</a>"
);
});

基础 Blocks


  
  
<div class="entry">
<h1>{{title}}</h1>
<div class="body">
{{#noop}}{{body}}{{/noop}}
</div>
</div>

  
  
Handlebars.registerHelper('noop', function(options) {
return options.fn(this);
});

noop helper 实际跟没有 helper 类似,只是传递上下文,返回字符串。Handlebars 把当前的上下文作为 this 。

内建 helper

with helper

根据模板传递的上下文解析模板


  
  
<div class="entry">
<h1>{{title}}</h1>
{{#with story}}
<div class="intro">{{{intro}}}</div>
<div class="body">{{{body}}}</div>
{{/with}}
</div>

当 JSON 对象包含嵌套属性时,不必再三重复父属性的名字。比如以下数据:


  
  
{
title: "First Post",
story: {
intro: "Before the jump",
body: "After the jump" }
}

helper 接收参数,参数为 JSON 属性的 上下文。


  
  
Handlebars.registerHelper('with', function(context, options) {
return options.fn(context);
});

简单迭代器 each helper

Handlebars 内建了 each 迭代器


  
  
<div class="comments">
{{#each comments}}
<div class="comment">
<h2>{{subject}}</h2>
{{{body}}}
</div>
{{/each}}
</div>

实现原理如下: 把 comments 数组的每一个元素作为上下文解析模板


  
  
Handlebars.registerHelper('each', function(context, options) {
var ret = "";
for(var i=0, j=context.length; i<j; i++) {
ret = ret + options.fn(context[i]);
}
return ret;
});

可以用 this 引用迭代元素


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

上下文:


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

结果:


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

当某一项为空时,可以用

{{else}}

表达式


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

通过

{{@index}}

可以引用当前的循环索引


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

{{@key}}

引用当前的键名:


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

数组迭代的第一步和最后一步用 @first 和 @last 变量表示, 对象迭代时仅 @first可用。

条件语句 if helper

如果条件参数返回 falseundefinednull"" 或 [](非真的值)时,Handlebars 将不渲染该块

Handlebars 内建了 if 和 unless 语句


  
  
{{#if isActive}}
<img src="star.gif" alt="Active">
{{/if}}

实现原理:根据传入的条件参数,判断是否解析模板


  
  
Handlebars.registerHelper('if', function(conditional, options) {
if(conditional) {
return options.fn(this);
}
});

Handlebars 还提供了 else 语句


  
  
{{#if isActive}}
<img src="star.gif" alt="Active">
{{else}}
<img src="cry.gif" alt="Inactive">
{{/if}}

unless helper

unless 跟 if 正好相反,如果表达式返回 false ,模板将被渲染。


  
  
<div class="entry">
{{#unless license}}
<h3 class="warning">WARNING: This entry does not have a license!</h3>
{{/unless}}
</div>

当 license 返回 false,Handlebars 将渲染 warning 。

log helper

记录上下文状态

{{log "Look at me!"}}

JavaScript 编译模板

模板可以包含在特殊的<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 模板,用 JSON 数据填充模板


  
  
var context = {title: "My New Post", body: "This is my first post!"}
var html = template(context);

最终结果:


  
  
<div class="entry">
<h1>My New Post</h1>
<div class="body">
This is my first post!
</div>
</div>

HTML 转义

不想转义用

{{{

模板:


  
  
<div class="entry">
<h1>{{title}}</h1>
<div class="body">
{{{body}}}
</div>
</div>

上下文数据:


  
  
{
title: "All about <p> Tags",
body: "<p>This is a post about <p> tags</p>"
}

最终结果:


  
  
<div class="entry">
<h1>All About <p> Tags</h1>
<div class="body">
<p>This is a post about <p> tags</p>
</div>
</div>

Handlebars.SafeString 方法不做转义,通常返回 new Handlebars.SafeString(result)。此种情形,你可能想手动转义参数:


  
  
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);
});

模板注释

{{! }}

或者

{{!-- --}}

  
  
<div class="entry">
{{! only output this author names if an author exists }}
{{#if author}}
<h1>{{firstName}} {{lastName}}</h1>
{{/if}}
</div>

模板注释不会输出,HTML 注释会输出


  
  
<div class="entry">
{{! This comment will not be in the output }}
<!-- This comment will be in the output -->
</div>

Partials 局部模板

{{> partialName}}

引入局部模板,局部模板可以使字符串,也可以是编译模板的函数。

var source = "<ul>{{#people}}<li>{{> link}}</li>{{/people}}</ul>";  

  
  
Handlebars.registerPartial('link', '<a href="/people/{{id}}">{{name}}</a>')
var template = Handlebars.compile(source);

  
  
var data = { "people": [
{ "name": "Alan", "id": 1 },
{ "name": "Yehuda", "id": 2 }
]};
template(data);
// Should render:
// <ul>
// <li><a href="/people/1">Alan</a></li>
// <li><a href="/people/2">Yehuda</a></li>
// </ul>

内建工具

转义字符串

Handlebars.Utils.escapeExpression(string)  

判断空值

Handlebars.Utils.isEmpty(value)  

扩展对象

Handlebars.Utils.extend(foo, {bar: true})  

转字符串

Handlebars.Utils.toString(obj)  

判断数组

Handlebars.Utils.isArray(obj)  

判断函数

Handlebars.Utils.isFunction(obj)  

原文地址:http://jinlong.github.io/2014/10/19/handlebars-docs/


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值