Backbone.js收集比较器按多个字段sorting?

this.col = Backbone.Collection.extend({ model: M, comparator: function(item) { return item.get("level"); } }); 

以上代码按级别sorting项目。 我想按级别sorting,然后按标题sorting。 我可以这样做吗? 谢谢。

@ amchang87的答案肯定有效,但另一个我发现工作只是返回一个可sorting的字段数组:

 this.col = Backbone.Collection.extend({ model: M, comparator: function(item) { return [item.get("level"), item.get("title")] } }); 

我还没有在多个浏览器中testing过,因为我认为它依赖于JS按照数组sorting的行为(基于它们的内容)。 它绝对适用于WebKit。

string连接工作良好,当按升序sorting多个字段,但它并没有为我工作,因为1)我必须支持asc / desc每场和2)某些领域是数字领域(即,我要10来2如果是升序)。 所以,下面是我使用的一个比较器function,可以满足我的需要。 它假设backbone集合有一个分配了“sortConfig”的variables,该variables是JSON对象的数组,具有字段名称和sorting顺序方向。 例如,

 { "sort" : [ { "field": "strField", "order": "asc" }, { "field": "numField", "order": "desc" }, ... ] } 

将上面的JSON对象指定为集合中的“sortConfig”,下面的函数将首先按照strField的升序进行Backbonesorting,然后按降序排列numField等。如果没有指定sorting顺序,则默认为升序sorting。

 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; } 

返回一个数组是不一致的,如果你需要sorting降序和一些升序…

我创build了一小组function,可用于将相关比较整数返回到主干比较器function:

骨干信息收集multisort

最主要的是骨干按一个项目的单个相对值进行sorting。 所以不能直接在一个集合中进行两次sorting,但我会尝试这个。

 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”的string… Javascript应该先由数字字符,然后每个字符sortingstring。 但是只要你的关卡有相同数量的数字,这只会起作用。 IE“001title”vs“200title”。 主要的想法是,你需要产生两个可比较的对象,行号或string,可以根据一个标准相互比较。

其他的解决scheme是使用下划线“groupby”你的级别,然后使用“sortby”手动sorting每个级别组,然后手动replace这个新创build的数组的基础集合。 你可以设置一个函数来做到这一点,只要集合“改变”。

hyong回答“启发”。

这也允许你在比较它之前改变数据,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; },