我可以成功地做到这一点:
App.SomeCollection = Backbone.Collection.extend({
comparator: function( collection ){
return( collection.get( 'lastName' ) );
}
});
如果我想要一个仅按'lastName'排序的集合,那就太好了。但我需要动态完成这种排序。有时,我需要改为排序,比如'firstName'。
我的彻底失败包括:
我尝试将指定变量的额外变量传递给sort()
。那没用。我也尝试了sortBy()
,但也没有用。我尝试将自己的函数传递给sort(),但这也不起作用。将用户定义的函数传递给sortBy()
只是为了使结果不具有each
方法,从而无法获得新分类的主干集合。
有人能提供一个实际的例子,通过一个未硬编码到比较器函数中的变量进行排序吗?或者你有任何黑客有效吗?如果没有,请拨打sortBy()
电话吗?
答案 0 :(得分:37)
有趣的问题。我会在这里尝试一下策略模式的变体。您可以创建排序函数的哈希,然后根据所选的哈希成员设置comparator
:
App.SomeCollection = Backbone.Collection.extend({
comparator: strategies[selectedStrategy],
strategies: {
firstName: function () { /* first name sorting implementation here */ },
lastName: function () { /* last name sorting implementation here */ },
},
selectedStrategy: "firstName"
});
然后,您可以通过更新selectedStrategy
属性的值来动态更改排序策略。
Collection.extend
。创建对象时,comparator
属性将被评估一次,因此除非被强制执行,否则它不会立即进行更改。可能有一种更简洁的方法可以做到这一点,但这证明了即时切换比较器功能:
var SomeCollection = Backbone.Collection.extend({
comparator: function (property) {
return selectedStrategy.apply(myModel.get(property));
},
strategies: {
firstName: function (person) { return person.get("firstName"); },
lastName: function (person) { return person.get("lastName"); },
},
changeSort: function (sortProperty) {
this.comparator = this.strategies[sortProperty];
},
initialize: function () {
this.changeSort("lastName");
console.log(this.comparator);
this.changeSort("firstName");
console.log(this.comparator);
}
});
var myCollection = new SomeCollection;
这里有jsFiddle来证明这一点。
我认为,所有问题的根源都是在创建对象时立即评估JavaScript对象文字的属性,因此如果要更改属性,则必须覆盖该属性。如果您尝试将某种切换写入属性本身,它将被设置为初始值并保持在那里。
这是一个很好的blog post,它在稍微不同的背景下讨论这个问题。
答案 1 :(得分:16)
通过为其分配新功能并调用sort来更改为比较器功能。
// Following example above do in the view:
// Assign new comparator
this.collection.comparator = function( model ) {
return model.get( 'lastname' );
}
// Resort collection
this.collection.sort();
// Sort differently
this.collection.comparator = function( model ) {
return model.get( 'age' );
}
this.collection.sort();
答案 2 :(得分:12)
所以,这是我真正有效的解决方案。
App.Collection = Backbone.Collection.extend({
model:App.Model,
initialize: function(){
this.sortVar = 'firstName';
},
comparator: function( collection ){
var that = this;
return( collection.get( that.sortVar ) );
}
});
然后在视图中,我必须使用M-I-C-K-E-Y M-O-U-S-E:
this.collections.sortVar = 'lastVar'
this.collections.sort( this.comparator ).each( function(){
// All the stuff I want to do with the sorted collection...
});
由于Josh Earl是唯一一个尝试解决方案的人,他确实引导我朝着正确的方向前进,我接受了他的回答。谢谢Josh:)
答案 3 :(得分:4)
这是一个古老的问题,但我最近有类似的需求(根据用户点击事件提供的标准对集合进行排序)并认为我与其他人共享解决此问题的解决方案。不需要硬编码的model.get('属性')。
我基本上使用Dave Newton的approach来扩展本机JavaScript数组,并将其定制为Backbone:
MyCollection = Backbone.Collection.extend({
// Custom sorting function.
sortCollection : function(criteria) {
// Set your comparator function, pass the criteria.
this.comparator = this.criteriaComparator(criteria);
this.sort();
},
criteriaComparator : function(criteria, overloadParam) {
return function(a, b) {
var aSortVal = a.get(criteria);
var bSortVal = b.get(criteria);
// Whatever your sorting criteria.
if (aSortVal < bSortVal) {
return -1;
}
if (aSortVal > bSortVal) {
return 1;
}
else {
return 0;
}
};
}
});
注意&#34; overloadParam&#34;。根据{{3}},Backbone使用Underscore&#34; sortBy&#34;如果你的比较器函数有一个param,如果它有两个参数,则为本机JS样式排序。我们需要后者,因此&#34; overloadParam&#34;。
答案 4 :(得分:3)
查看source code,似乎有一种简单的方法,将比较器设置为字符串而不是函数。这是有效的,给出Backbone.Collection mycollection:
mycollection.comparator = key;
mycollection.sort();
答案 5 :(得分:0)
这就是我最终为我正在开发的应用做的事情。在我的收藏中,我有:
comparator: function(model) {
var methodName = applicationStateModel.get("comparatorMethod"),
method = this[methodName];
if (typeof(method === "function")) {
return method.call(null, model);
}
}
现在我可以为我的集合添加几个不同的方法:fooSort(),barSort()和bazSort()。
我希望fooSort成为默认值,所以我在我的状态模型中设置它是这样的:
var ApplicationState = Backbone.Model.extend({
defaults: {
comparatorMethod: "fooSort"
}
});
现在我要做的就是在我的视图中编写一个函数,根据用户点击的内容更新“comparatorMethod”的值。我将集合设置为侦听这些更改并执行sort(),并将视图设置为侦听排序事件并执行render()。
BAZINGA !!!!