以与backbone.js相反的顺序sortingstring

我正在尝试按相反顺序对Backbone.js集合进行sorting。 以前有关于如何用整数做这个回答,但没有用string。

var Chapter = Backbone.Model; var chapters = new Backbone.Collection; chapters.comparator = function(chapter) { return chapter.get("title"); }; chapters.add(new Chapter({page: 9, title: "The End"})); chapters.add(new Chapter({page: 5, title: "The Middle"})); chapters.add(new Chapter({page: 1, title: "The Beginning"})); alert(chapters.pluck('title')); 

上面的代码把A – > Z中的章节sorting,但是如何编写一个从Z – > Asorting的比较器呢?

有两种版本的比较函数,你可以使用sortBy版本 – 在示例中显示,它带有一个参数,或者sorting – 你可以返回一个更标准的sorting函数, 文档说:

“sortBy”比较函数采用一个模型并返回一个数字或string值,通过该值可以将模型相对于其他模型sorting。 “sort”比较函数有两个模型,如果第一个模型应该在第二个模型之前,则返回-1,如果它们具有相同的等级,则返回0;如果第一个模型应该在之后,则返回1。

所以在这种情况下,我们可以写一个不同的比较器函数:

 var Chapter = Backbone.Model; var chapters = new Backbone.Collection; chapters.comparator = function(chapterA, chapterB) { if (chapterA.get('title') > chapterB.get('title')) return -1; // before if (chapterB.get('title') > chapterA.get('title')) return 1; // after return 0; // equal }; chapters.add(new Chapter({page: 9, title: "The End"})); chapters.add(new Chapter({page: 5, title: "The Middle"})); chapters.add(new Chapter({page: 1, title: "The Beginning"})); alert(chapters.pluck('title')); 

所以你应该得到一个回应:

 "The Middle", "The End", "The Beginning" 

你可以:

  • 获取string中每个字符的char代码,
  • 0xffffstring.charCodeAt的最大返回值)中减去每个值,
  • 使用String.fromCharCode将其转换回“否定”string

那将是你的sorting键。

 chapters.comparator = function(chapter) { return String.fromCharCode.apply(String, _.map(chapter.get("title").split(""), function (c) { return 0xffff - c.charCodeAt(); }) ); } 

瞧:

 > console.log(chapters.pluck('title')); ["The Middle", "The End", "The Beginning"] 

注意:如果比较string很长(如65 kb或更多),则可能会遇到麻烦(请参阅下面的Matt评论)。 为了避免这种情况,并加快比较,只需使用较短的比较string。 (在上面的例子中,你可以使用chapter.get("title").slice(0, 100).split("")来代替。)你需要多长时间取决于你的应用程序。

如果您使用的是非数字值,则没有明显的方法来进行反向sorting。 主干使用来自_.sortBy()_.sortedIndex()方法来对基于比较器的模型进行sorting,并且这些方法自动按升序sorting。 天真的做法是使用chapters.pluck('title').reverse()作为pluck的结果将是一个数组。 但是在某些Collection方法上调用reverse会使Collection模型反转,所以下次调用它时,模型会按升序排列。 你总是可以这样做:

 var results = [], titles = chapters.pluck('title'); for(var i=0, len=titles.length; i<len; i++) { results.push(titles[i]); } results.reverse(); 

这不会影响Backbone集合中的models数组,因为它会在内存中创build一个全新的结果数组,但保留对原始模型的引用,所以调用诸如save东西仍然会更新Collection状态。

但是,这不是很优雅,并且在任何时候想要反转结果都会在整个项目中创build大量额外的代码。 我想我们可以做得更好。

为了使这个工作,你需要在你的比较器方法中执行一些笨拙的JavaScript忍者来做这个工作 – 注意这是未经testing的:

 chapters.comparator = function(chapter) { var alphabet = '0123456789abcdefghijklmnopqrstuvwxyz', title = chapter.get('title').toLowerCase(), inverse_title = '', index; for(var i=0, len=title.length; i<len; i++) { index = alphabet.indexOf(title.charAt(i)); if(index === -1) { inverse_title += title.charAt(i); continue; } inverse_title += alphabet.charAt(alphabet.length - index - 1); } return inverse_title; }; 

这个概念可能需要改进以考虑符号等,但实际上它将比较器串反转为使得“Z”变成“0”,“Y”变成“1”等,这将产生相反的sorting你后。

由于Backbone仅使用.sortBy方法,只需在您自己的逻辑中进行代理:

 collectionInQuestion.sortBy = function () { var models = _.sortBy(this.models, this.comparator); if (forSomeReason) { models.reverse(); } return models; }; 

..或将其添加到其他地方..

 TweakedCollection = Backbone.Collection.extend({ sortBy: [...] }) 

我刚刚解决了表格sorting类似的问题,我想分享代码,因为我没有find这些答案很多的帮助:

 events: { 'click th.sortable': function(e) { var $this = $(e.target), order = $this.hasClass('asc') ? 'desc' : 'asc', field = $this.data('field'); /* this is a string */ $this.siblings().addBack().removeClass('asc desc'); $this.addClass( order ); this.bodyView.collection.comparator = field; this.bodyView.collection.sort(); if ( order === 'desc' ) this.bodyView.collection.models.reverse(); this.bodyView.render(); } }, 

在这种情况下,我只是将比较器设置为string而不是函数; 该string必须是您想要sorting的属性的名称。 然后,如果顺序必须相反,我只需在模型上调用相反的方法。

chapter.get之前加上minus

 chapters.comparator = function(chapter) {    return -chapter.get("title"); };