在小胡子中,如何获得当前部分的索引

我正在使用胡子和使用数据

{ "names": [ {"name":"John"}, {"name":"Mary"} ] } 

我的小胡子模板是:

 {{#names}} {{name}} {{/names}} 

我想要能够做的是得到数组中的当前数字的索引。 就像是:

 {{#names}} {{name}} is {{index}} {{/names}} 

并打印出来

 John is 1 Mary is 2 

胡须可以得到吗? 或用把手或其他扩展?

作为参考,这个function现在内置于与小胡子兼容的把手。

使用{{@index}}

 {{#names}} {{name}} is {{@index}} {{/names}} 

约翰是0

玛丽是1

这是我如何在JavaScript中做到这一点:

 var idx = 0; var data = { "names": [ {"name":"John"}, {"name":"Mary"} ], "idx": function() { return idx++; } }; var html = Mustache.render(template, data); 

您的模板:

 {{#names}} {{name}} is {{idx}} {{/names}} 

在handlebars.js中,你可以用辅助函数完成这个任务。 (事实上​​,这里提到的关于句柄的好处之一就是你可以使用助手,而不必在调用模板之前重写对象。

所以,你可以这样做:

  var nameIndex = 0; Handlebars.registerHelper('name_with_index', function() { nameIndex++; return this.name + " is " + nameIndex; }) 

然后,你的模板可以是这样的:

 {{#names}} <li>{{name_with_index}}</li> {{/names}} 

您的数据与以前相同,即:

 { "names": [ {"name":"John"}, {"name":"Mary"} ] }; 

你得到这个输出:

 <li>John is 1</li> <li>Mary is 2</li> 

为了实现这个效果,每次模板被渲染时,nameIndex都需要被重置,所以要在列表的开头有一个重置助手。 所以完整的代码如下所示:

  var data = { "names": [ {"name":"John"}, {"name":"Mary"} ] }; var templateSource = "<ul>{{reset_index}}{{#names}}<li>{{name_with_index}}</li>{{/names}}</ul>"; var template = Handlebars.compile(templateSource); var helpers = function() { var nameIndex = 0; Handlebars.registerHelper('name_with_index', function() { nameIndex++; return this.name + " is " + nameIndex; }); Handlebars.registerHelper('reset_index', function() { nameIndex = 0; }) }(); var htmlResult= template(data); $('#target').html(htmlResult); var htmlResult2= template(data); $('#target2').html(htmlResult2); 

(这可以正确地呈现模板两次。)

您可以在对象列表中运行以下循环。

该解决scheme具有以下优点:

  • 不更改模型数据
  • 索引可以被访问多次

码:

 for( var i=0; i< the_list.length; i++) { the_list[i].idx = (function(in_i){return in_i+1;})(i); } 

说明:

使用函数而不是variables名称,所以数据不会发生变化。 Closure用于在循环中创build函数时返回“i”的值,而不是在循环结束时的值i。

这里的好帮手:

 // {{#each_with_index records}} // <li class="legend_item{{index}}"><span></span>{{Name}}</li> // {{/each_with_index}} Handlebars.registerHelper("each_with_index", function(array, fn) { var buffer = ""; for (var i = 0, j = array.length; i < j; i++) { var item = array[i]; // stick an index property onto the item, starting with 1, may make configurable later item.index = i+1; // show the inside of the block buffer += fn(item); } // return the finished buffer return buffer; }); 

来源: https : //gist.github.com/1048968

胡须的一个更好的方法是使用一个函数,使用indexOf获取索引:

 var data = { names: [ {"name":"John"}, {"name":"Mary"} ], index: function() { return data.names.indexOf(this); } }; var html = Mustache.render(template, data); 

在您的模板中:

 {{#names}} {{name}} is {{index}} {{/names}} 

缺点是这个index函数有数组硬编码的data.names使它更加dynamic化,我们可以使用另一个函数如下:

 var data = { names: [ {"name":"John"}, {"name":"Mary"} ], index: function() { return function(array, render) { return data[array].indexOf(this); } } }; var html = Mustache.render(template, data); 

在您的模板中的用法:

 {{#names}} {{name}} is {{#index}}names{{/index}} {{/names}} 

另外一个小缺点就是你必须把数组名称传递给索引函数,在这个例子中, {{#index}}names{{/index}}

如果你可以控制JSONstring的输出,那么试试看。

 { "names": [ {"name":"John", "index":"1"}, {"name":"Mary", "index":"2"} ] } 

所以,当你使你的JSONstring,添加索引作为每个对象的另一个属性。

我的主要用例是能够在项目上放置“主动”类。 我搞混了一个“等于”帮手和“index_for_each”帮手,但它太复杂了。

相反,我想出了以下基本的“积极”帮手。 这是非常具体的,但是对于任何菜单/select列表场景来说这是一个常见的用例:

用法:

  <ul> {{{active 2}}} {{#each menuItem}} <li class="{{{active}}}">{{this}}</li> {{/each}} </div> 

会使第三个菜单项有一个“class ='active'”。

助手在这里(这是CoffeeScript版本):

 active = 0 cur = 0 handlebars.registerHelper 'active', (item, context) -> if arguments.length == 2 active = item cur = 0 '' else if cur++ == active 'active' 

只要你没有进入多个数组,你可以将索引存储在助手中,并在上下文发生变化时递增。 我正在使用类似于以下内容的东西:

 var data = { foo: [{a: 'a', 'b': 'a'}, {'a':'b', 'b':'b'}], i: function indexer() { indexer.i = indexer.i || 0; if (indexer.last !== this && indexer.last) { indexer.i++; } indexer.last = this; return String(indexer.i); } }; Mustache.render('{{#foo}}{{a}}{{i}}{{b}}{{i}}{{/foo}}', data); 

(在节点4.4.7中testing,小胡子2.2.1。)

如果你想要一个很好的干净的函数方式来做到这一点,这不涉及全局variables或变异对象本身,使用此函数;

 var withIds = function(list, propertyName, firstIndex) { firstIndex |= 0; return list.map( (item, idx) => { var augmented = Object.create(item); augmented[propertyName] = idx + firstIndex; return augmented; }) }; 

在组装视图时使用它;

 var view = { peopleWithIds: withIds(people, 'id', 1) // add 'id' property to all people, starting at index 1 }; 

这种方法的精妙之处在于它创build了一套新的“视图模型”对象,使用旧的集合作为原型。 您可以像读取person.firstName一样阅读person.firstName 。 但是,这个函数根本不会改变你的人员对象,所以其他代码(可能依赖于ID属性不在那里)不会受到影响。

algorithm是O(N),非常快速。