Handlebars.js 块级Helpers

块级的Helpers可以在新的数据上下文下自定义迭代器和其他helpers。


基础

下面定义一个简单的块级Helpers

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

noop helper接受一个option hash,这个option包含一个函数(option.fn),它就和普通编译出的模板一样,接受一个数据上下文,返回一个字符串。

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

Handlebars可以通过this调用当前的数据上下文。


The with helper

基于刚才的noop helper,with helper的使用就很明显了。使用with helper,我们可以限定任意的数据上下文。

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

当你的JSON包含很多重要的属性时,这个helper会非常有用。你需要一直重复父级的名称,例如使用下面的上下文

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

with helper和上面的noop很像。接受一个参数,渲染到{{mustache}}块中。

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


简单的迭代器

块级helper的一个最常见的用法是自定义迭代器。事实上,所有的内置helper都块级helper一样。下面我们看一下内置的each helper如何工作。

<div class="entry">
  <h1>{{title}}</h1>
  {{#with story}}
    <div class="intro">{{{intro}}}</div>
    <div class="body">{{{body}}}</div>
  {{/with}}
</div>
<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;
});

传入数据上下文(context),循环它们,生成一个字符串,返回。

现在,我们很容易看出如何实现更加复杂的迭代器。例如生成一个<ul>列表

{{#list nav}}
  <a href="{{url}}">{{title}}</a>
{{/list}}

使用下面的数据

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

list helper和原生的each helper不一样

Handlebars.registerHelper('list', function(context, options) {
  var ret = "<ul>";

  for(var i=0, j=context.length; i<j; i++) {
    ret = ret + "<li>" + options.fn(context[i]) + "</li>";
  }

  return ret + "</ul>";
});


条件判断

另一个常见的应用就是条件判断。同样的,内置的ifunless像普通的块级helper一样实现。

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

控制结构通常不改变当前的数据上下文,但是会根据一些变量判断是否渲染相应的块。

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

当使用条件判断的时候,常常需要在判断结果为false的时候插入相应的HTML块,Handlebar使用else解决这个问题。

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

Handlebar使用options.inverse来生成else的内容,如果没有inverse函数,模板会自动创建一个空函数。

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


Hash 参数

和普通的helper一样,块级helper可以接受一个hash作为最后一个参数。我们来改进一下list helper,让<ul>接受任意多的属性。

{{#list nav id="nav-bar" class="top"}}
  <a href="{{url}}">{{title}}</a>
{{/list}}

Handlebar把最后的hash传给opton.hash,这样可以接受任意参数,如果模板没有传hash参数,option.hash会是{}

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

  return "<ul " + attrs + ">" + context.map(function(item) {
    return "<li>" + options.fn(item) + "</li>";
  }).join("\n") + "</ul>";
});

块级Helper还可以传递私有变量,这样就可以传入数据上下文之外的数据。

例如,我们生成一个list,包含当前列的序号。

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

  for (var i=0; i<context.length; i++) {
    if (options.data) {
      data = Handlebars.createFrame(options.data || {});
      data.index = i;
    }

    out += "<li>" + options.fn(context[i], { data: data }) + "</li>";
  }

  out += "</ul>";
  return out;
});

通过data传递私有变量。


空白处理

使用~会省略模板任意一侧的空格

{{#each nav ~}}
  <a href="{{url}}">
    {{~#if test}}
      {{~title}}
    {{~^~}}
      Empty
    {{~/if~}}
  </a>
{{~/each}}

使用下面的数据

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

结果输出无换行和空格

<a href="foo">bar</a><a href="bar">Empty</a>

handlebars.js中文文档



标签: , ,

无觅相关文章插件,快速提升流量