this.col = Backbone.Collection.extend({
model: M,
comparator: function(item) {
return item.get("level");
}
});
以上代码按级别对项目进行排序。我想按级别排序,然后按标题排序。我能这样做吗?感谢。
答案 0 :(得分:73)
@ amchang87的答案肯定有效,但我发现的另一个工作就是返回一个可排序字段的数组:
this.col = Backbone.Collection.extend({
model: M,
comparator: function(item) {
return [item.get("level"), item.get("title")]
}
});
我还没有在多个浏览器中对此进行测试,因为我认为它依赖于JS在数组的排序顺序中的行为(基于它们的内容)。它肯定适用于WebKit。
答案 1 :(得分:7)
字符串连接在按升序排序多个字段时工作正常,但它对我不起作用,因为1)我必须支持每个字段的asc / desc和2)某些字段是数字字段(即,我想要10到如果是提升,请来2。)所以,下面是我使用的比较器功能,可以满足我的需求。它假设主干集合具有一个赋值为'sortConfig'的变量,该变量是一个带有字段名称和排序顺序方向的JSON对象数组。例如,
{
"sort" : [
{
"field": "strField",
"order": "asc"
},
{
"field": "numField",
"order": "desc"
},
...
]
}
上面的JSON对象被指定为集合的'sortConfig',下面的函数将首先按strField按升序排序Backbone,然后按降序排序按numField排序等。如果没有指定排序顺序,则排序默认升序。
multiFieldComparator: function(one, another) {
// 'this' here is Backbone Collection
if (this.sortConfig) {
for (var i = 0; i < this.sortConfig.length; i++) {
if (one.get(this.sortConfig[i].field) > another.get(this.sortConfig[i].field)) {
return ("desc" != this.sortConfig[i].order) ? 1 : -1;
} else if (one.get(this.sortConfig[i].field) == another.get(this.sortConfig[i].field)) {
// do nothing but let the loop move further for next layer comparison
} else {
return ("desc" != this.sortConfig[i].order) ? -1 : 1;
}
}
}
// if we exited out of loop without prematurely returning, the 2 items being
// compared are identical in terms of sortConfig, so return 0
// Or, if it didn't get into the if block due to no 'sortConfig', return 0
// and let the original order not change.
return 0;
}
答案 2 :(得分:2)
如果您需要对降序进行排序以及某些升序......返回数组不一致...
我创建了一小组函数,可用于将相关的比较整数返回给Backbone Comparator函数:
答案 3 :(得分:1)
主要的是Backbone按一个项目的相对值排序到另一个项目。因此,在单个集合中排序两次并不是直接可行的,但我会尝试这样做。
this.col = Backbone.Collection.extend({
model: M,
comparator: function(item) {
// make sure this returns a string!
return item.get("level") + item.get("title");
}
});
这样做会返回一串像“1Cool”,“1title”,“2newTitle”...... Javascript应首先按数字字符对字符串进行排序,然后对每个字符进行排序。但只有您的等级具有相同的位数时,这才会起作用。 IE“001title”vs“200title”。但主要的想法是你需要生成两个可比较的对象,排成一个数字或字符串,可以根据一个标准相互比较。
其他解决方案是使用下划线“groupby”您的级别,然后使用“sortby”手动排序每个级别组,然后使用这个新创建的数组手动替换底层集合。每当集合“更改”时,您可以设置一个函数来执行此操作。
答案 4 :(得分:0)
这也允许你在比较之前更改数据,valueTransforms是一个对象,如果该对象中有一个具有函数的属性,它将被使用。
/*
* @param {Object} sortOrders ie:
* {
* "description": "asc",
* "duedate": "desc",
* }
* @param {Object} valueTransforms
*/
setMultiFieldComparator: function(sortOrders, valueTransforms) {
var newSortOrders = {}, added = 0;
_.each(sortOrders, function(sortOrder, sortField) {
if (["asc", "desc"].indexOf(sortOrder) !== -1) {
newSortOrders[sortField] = sortOrder;
added += 1;
}
});
if (added) {
this.comparator = this._multiFieldComparator
.bind(this, newSortOrders, valueTransforms || this.model.prototype.valueTransforms || {});
} else {
this.comparator = null;
}
},
_multiFieldComparator: function(sortOrders, valueTransforms, one, another) {
var retVal = 0;
if (sortOrders) {
_.every(sortOrders, function(sortOrder, sortField) {
var oneValue = one.get(sortField),
anotherValue = another.get(sortField);
if (valueTransforms[sortField] instanceof Function) {
oneValue = valueTransforms[sortField](oneValue);
anotherValue = valueTransforms[sortField](anotherValue);
}
if (oneValue > anotherValue) {
retVal = ("desc" !== sortOrder) ? 1 : -1;
} else if (oneValue < anotherValue) {
retVal = ("desc" !== sortOrder) ? -1 : 1;
} else {
//continue
return true;
}
});
}
return retVal;
},