方法一:自定义访问器
如果您可以控制上下文(并且您可能这样做),您可以使用属性访问器来实现它。假设您的上下文包含混乱顺序的评论:
var context = {
comments: [
{ idx:6, text:'violet' },
{ idx:1, text:'orange' },
{ idx:0, text:'red' },
{ idx:5, text:'indigo' },
{ idx:3, text:'green' },
{ idx:2, text:'yellow' },
{ idx:4, text:'blue' },
],
};
您可以comments
在渲染模板之前对数组进行适当的排序(请注意,对于数值,您可以减去它们以获得自然排序):
context.comments.sort( function(a,b) { return a.idx - b.idx; } );
这样做的问题是会修改上下文对象,而您可能不想这样做。一种解决方案是提供一个自定义访问器,该访问器将返回按某些自定义属性排序的评论。我们可以这样做:
Object.defineProperty( context, 'commentsByIdx', {
get: function() {
// note that we call concat() to create a copy of
// the array; otherwise we are modifying the
// the original array, which is a side effect
return this.comments.concat()
.sort( function(a,b) { return a.idx - b.idx } );
}
});
你可以在这里看到这个解决方案:http: //jsfiddle.net/Jammerwoch/ShZLY/
方法二:Handlebars Block Helper
另一种方法是实现Handlebars 块助手。如果您对上下文没有太多控制权(或者不想用自定义属性污染它),这种方法会更好。只需注册一个 Handlebars 助手:
Handlebars.registerHelper('eachByIdx', function(context,options){
var output = '';
var contextSorted = context.concat()
.sort( function(a,b) { return a.idx - b.idx } );
for(var i=0, j=contextSorted.length; i<j; i++) {
output += options.fn(contextSorted[i]);
}
return output;
});
并在您的模板中这样称呼它:
{{#eachByIdx comments}}
<li>{{text}}</li>
{{/eachByIdx}}
在此处查看实际操作:http: //jsfiddle.net/Jammerwoch/aeCYg/1/
总而言之,我发现第一种方法更可取,因为它创建了一个新的数据视图,这在 Handlebars 之外可能很有用。此外,对于 Handlebars 代码的普通读者来说,它会更有意义。