Handlebars中文文档 - 块级helpers(译自官方版)

原文在此:original article in here

译注:
1. 一般来说context,翻译为【上下文】,在 JS 中多数时候就是指函数执行时的 this 的引用。
2. 看,不是最重要的,多写代码,照着例子写写,再改改,看看结果,就知道怎么回事了。


块级 helpers 使用自定义的迭代器,其他的 helpers 都可以使用一个新的上下文来执行内部的代码块。

基础

先定义一个简单的块级 helper,它只是简单的执行一下这块代码,就跟没有用这个helper一样。

{{title}}

{{#noop}}{{body}}{{/noop}}

这个 noop helper 接受一个 options 对象。这个对象有一个叫 options.fn 的方法,这个方法的用法就跟普通的编译过的 Hanldebars 模板的用法一样。所不同的就是,这个函数执行时会带有一个上下文,并且会返回一个字符串。

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

Handlebars 在执行 helpers 的时候,总是会将 this 指向当前的上下文,所以,你只需用 this 来调用这一块代码,就可以在当前的上下文中求值了。

with helper

在上面介绍的 noop helper 的基础上,很容易的就能想到应该如何实现 with helper 了。这里呢,不是用当前的上下文来执行代码块,我们可以使用任意的模板所传递进来的上下文。

{{title}}

{{#with story}}
{{{intro}}}
{{{body}}}
{{/with}}

在你使用的JSON嵌套非常深的时候,就会觉得这个helper 非常有帮助了,否则的话,每次都需要先写上很长的父级属性。比如上面的模板可以使用下面的这段JSON:

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

实现这种helper,就跟实现一堆 noop helper 没什么区别。要注意的是,helpers 可以接受参数,并且对参数的求值就跟直接使用 {{mustache}} 表达式一样一样地。

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

helpers 接受参数的顺序跟传递进来的顺序相同。

简单的迭代器

使用块级 helpers 的一个非常常见的目的就是定义一个自定义的迭代器。实际上,所有的 Handlebars 内置的 helpers 就是一些常规的 块级 helpers。我们一起来看看内置的 each helper 是如何工作的:

{{title}}

{{#with story}}
{{{intro}}}
{{{body}}}
{{/with}}
{{#each comments}}

{{subject}}

{{{body}}}
{{/each}}

在这里的情况下,我们希望对 comments 数组的每一项都执行 传递给 each 的这一块代码。

Handlebars.registerHelper('each', function(context, options) {
  var ret = "";

  for(var i=0, j=context.length; i

这样,我们迭代传进来的参数的每一个项,并在每一次迭代的时候执行一次块中的代码。在我们迭代的过程中,还构建了一个字符串,并最终返回这个字符串。

可以看出,你也可以很容易的实现一个更高级的迭代器。例如,我们创建一个迭代器,可以生成

    的包裹容器,并且把每一个元素的计算结果包裹到
  • 中去。

    {{#list nav}}
      {{title}}
    {{/list}}
    

    可以使用类似下面的上下文来执行模板:

    {
      nav: [
        { url: "http://www.yehudakatz.com", title: "Katz Got Your Tongue" },
        { url: "http://www.sproutcore.com/block", title: "SproutCore Blog" },
      ]
    }
    

    这个 helper 跟内置的 each helper 没有太大的不同。

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

    你当然也可以使用类似 underscore.js 或 SproutCore's 的类库,让代码看起来更精简漂亮些。使用 SproutCore's 的示例如下:

    Handlebars.registerHelper('list', function(context, options) {
      return "
      " + context.map(function(item) { return "
    • " + options.fn(item) + "
    • "; }).join("\n") + "
    "; });

    条件

    使用 helpers 的另一个常见需求就是实现条件判断。
    再次重申一遍,Handlebars 内置的 ifunless 控制结构就是使用常规的 helpers 来实现的。

    {{#if isActive}}
      Active
    {{/if}}
    

    控制结构一般不会改变上下文,只是要根据一些变量来决定是否要执行这一块代码。

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

    在写控制结构的时候,经常需要在模板中提供一块 条件求值返回false时 执行的模板代码。Handlebars 给 helpers 提供了通用的 else 功能来解决这个问题。

    {{#if isActive}}
      Active
    {{else}}
      Inactive
    {{/if}}
    

    Handlebars 以 options.inverse 的形式来支持 else 块中的代码。如果模板没有提供条件取反的模板,Handlebars会自动的创建一个 空函数,这样你就不必去检查 inverse 是否存在了。

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

    Handlebars 还给 helpers 提供了额外的元数据,附加在 options 对象上面。继续阅读下面的例子。

    哈希参数

    就像普通的 helpers,块级 helpers 可以接受一个可选的对象作为最后一个参数。我们一起重温一下 list helper,并让他可以接受任意数量的可选属性,并且把添加到我们要创建的

      元素上。

      {{#list nav id="nav-bar" class="top"}}
        {{title}}
      {{/list}}
      

      Handlebars 以 options.hash 的形式把最后传进来的键值对挂在上来。这样就更容易接受不定数量的参数了,同时接受一个可选的对象。如果模板没有提供哈希参数,Handlebars 会自动的传一个空对象({}),这样你就不必检查哈希参数是否存在了。

      Handlebars.registerHelper('list', function(context, options) {
        var attrs = Em.keys(options.hash).map(function(key) {
          key + '="' + options.hash[key] + '"';
        }).join(" ");
      
        return "
        " + context.map(function(item) { return "
      • " + options.fn(item) + "
      • "; }).join("\n") + "
      "; });

      哈希参数提供了一个强大的方法来给 helper 提供任意数量的可选参数,而且避免了由可选性导致的复杂语法。

      块级helper还可以往它的子模板中注入私有变量。在一些情况下会很有帮助,比如需要把一些不在原来上下文中的数据插进来。

      例如,在循环一个列表的时候,你需要以私有变量的形式提供当前的索引index值。

      {{#list array}}
        {{@index}}. {{title}}
      {{/list}}
      Handlebars.registerHelper('list', function(context, options) {
        var out = '
      
      <
      
      ul>', data;
      
        for (var i=0; i";
        }
      
        out += "
    "; return out; });

    私有属性通过 data 选项来提供,并且在所有的内部作用域内都可以使用。

    要保证每次带着 data 执行代码块的时候都生成一个新的 data 帧。否则的话,后面的 helpers 可能会意外的改变前面的变量。

    还要确保在试图跟已存在的 data 对象交互之前 data 对象已经存在了。私有变量的行为是有条件编译的,有一些模板可能并没有创建这个字段。

    空白管理

    模板中的空白可以忽略,mustache声明的两边都可以,只需添加一个 ~ 字符即可。写了这个之后,这一边的所有空白都会被移除,直到最近的Handlebars表达式或这一边的非空白字符。

    {{#each nav ~}}
      
        {{~#if test}}
          {{~title}}
        {{~^~}}
          Empty
        {{~/if~}}
      
    {{~/each}}
    

    用这个上下文:

    {
      nav: [
        {url: 'foo', test: true, title: 'bar'},
        {url: 'bar'}
      ]
    }
    

    得出的结果没有换行,也没有格式化用的空白符:

    barEmpty
    

    转载请注明来自超2真人
    本文链接:http://www.peichao01.com/static_content/doc/html/introduce-handlebars-helpers.html

你可能感兴趣的:(handlebars,文档,中文文档,helpers,译文)