Buy Handlebars swag on DevSwag!

你可以使用 Handlebars 轻松的创建语义化模板。
Handlebars 兼容 Mustache 模板。你可以在 Handlebars 中直接使用 Mustache 模板。

Download: 3.0.1 Download: runtime-3.0.1

快速入门

Handlebars 模板看起来很像 HTML ,Handlebars 表达式嵌入在 HTML 中。

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

Handlebars 表达式以 {{属性名}} 的方式插入数据。

高级教程:表达式


你可以在 HTML 中使用 <script> 标签存放模板

<script id="entry-template" type="text/x-handlebars-template">
  <div class="entry">
    <h1>{{title}}</h1>
    <div class="body">
      {{body}}
    </div>
  </div>
</script>

在 JavaScript 中获取 <scrit> 中的模板并编译模板

var source   = $("#entry-template").html();
var template = Handlebars.compile(source);

建议初学者跳过预编译章节

还可以预编译你的模板。预编译后的模板只需使用 handlebars.runtime.js 渲染,这样可以提高性能并减少文件大小。在移动设备中这样做非常有意义(因为移动设备的性能和网络状态都没有PC好)。

高级教程:预编译


传入数据,执行 Handlebars 返回 渲染后的 HTML。

var source   = $("#entry-template").html();
var template = Handlebars.compile(source);

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 转义

遇到 HTML标签时 Handlebars 会返回转义后的 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 &lt;p&gt; tags</p>"
}

渲染结果:

<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>

Handlebars 不会转义 Handlebars.SafeString 。如果你自定义了一个 helper 返回 HTML 代码,你需要返回 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);
});

new Handlebars.SafeString() 会标识传入参数是“安全的”,所以即使你不使用 {{{ 。Handlebars 也不会转义。

示例

块表达式

块表达式允许你定义helper,用不同的数据上下文(context)调用一段模板。下面我们定义一个生成列表的helper:

快表达式允许你自定义 helper,使用当前传入参数作为上下文调用模板。

创建一个用于生产列表的快表达式

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

渲染数据如下所示:

{
  people: [
    {firstName: "Yehuda", lastName: "Katz"},
    {firstName: "Carl", lastName: "Lerche"},
    {firstName: "Alan", lastName: "Johnson"}
  ]
}

we would create a helper named list to generate our HTML list. The helper receives the people as its first parameter, and an options hash as its second parameter. The options hash contains a property named fn, which you can invoke with a context just as you would invoke a normal Handlebars template.

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

When executed, the template will render:

<ul>
  <li>Yehuda Katz</li>
  <li>Carl Lerche</li>
  <li>Alan Johnson</li>
</ul>

Block helpers have more features, such as the ability to create an else section (used, for instance, by the built-in if helper).

Since the contents of a block helper are escaped when you call options.fn(context), Handlebars does not escape the results of a block helper. If it did, inner content would be double-escaped!

Learn More: Block Helpers

Handlebars Paths

Handlebars supports simple paths, just like Mustache.

<p>{{name}}</p>

Handlebars also supports nested paths, making it possible to look up properties nested below the current context.

<div class="entry">
  <h1>{{title}}</h1>
  <h2>By {{author.name}}</h2>

  <div class="body">
    {{body}}
  </div>
</div>

That template works with this context

var context = {
  title: "My First Blog Post!",
  author: {
    id: 47,
    name: "Yehuda Katz"
  },
  body: "My first post. Wheeeee!"
};

This makes it possible to use Handlebars templates with more raw JSON objects.

Nested handlebars paths can also include ../ segments, which evaluate their paths against a parent context.

<h1>Comments</h1>

<div id="comments">
  {{#each comments}}
  <h2><a href="/posts/{{../permalink}}#{{id}}">{{title}}</a></h2>
  <div>{{body}}</div>
  {{/each}}
</div>

Even though the link is printed while in the context of a comment, it can still go back to the main context (the post) to retrieve its permalink.

The ../ path segment references the parent template scope, not one level up in the context. This is because block helpers can invoke a block with any context, so the notion of "one level up" isn't particularly meaningful except as a reference to the parent template scope.

Handlebars also allows for name conflict resolution between helpers and data fields via a this reference:

<p>{{./name}} or {{this/name}} or {{this.name}}</p>

Any of the above would cause the name field on the current context to be used rather than a helper of the same name.

Template comments with {{!-- --}} or {{! }}.

You can use comments in your handlebars code just as you would in your code. Since there is generally some level of logic, this is a good practice.

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

The comments will not be in the resulting output. If you'd like the comments to show up. Just use html comments, and they will be output.

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

Any comments that must contain }} or other handlebars tokens should use the {{!-- --}} syntax.

Helpers

Handlebars helpers can be accessed from any context in a template. You can register a helper with the Handlebars.registerHelper method.

<div class="post">
  <h1>By {{fullName author}}</h1>
  <div class="body">{{body}}</div>
  <h1>Comments</h1>
  {{#each comments}}
  <h2>By {{fullName author}}</h2>
  <div class="body">{{body}}</div>
  {{/each}}
</div>

when using this context and helpers:

var context = {
  author: {firstName: "Alan", lastName: "Johnson"},
  body: "I Love Handlebars",
  comments: [{
    author: {firstName: "Yehuda", lastName: "Katz"},
    body: "Me too!"
  }]
};

Handlebars.registerHelper('fullName', function(person) {
  return person.firstName + " " + person.lastName;
});

results in:

<div class="post">
  <h1>By Alan Johnson</h1>
  <div class="body">I Love Handlebars</div>
  <h1>Comments</h1>
  <h2>By Yehuda Katz</h2>
  <div class="body">Me Too!</div>
</div>

Helpers receive the current context as the this context of the function.

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

when using this context and 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>"
  );
});

results in:

<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>

If your helper returns HTML that you do not want escaped, make sure to return a new Handlebars.SafeString.

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.

Learn More: API Reference

<!-- End .contents

发现翻译错误?告诉我们。
Fork me on GitHub