在小胡子中,如何获得当前部分的索引
我正在使用胡子和使用数据
{ "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),非常快速。