使用Backbone.js反向排序顺序

Dre*_*ams 89 javascript backbone.js

使用Backbone.js我已经设置了一个带比较器功能的集合.这很好地排序模型,但我想颠倒顺序.

如何按降序排序模型而不是升序?

Inf*_*igo 133

好吧,你可以从比较器返回负值.例如,如果我们采用Backbone网站上的示例并希望颠倒顺序,它将如下所示:

var Chapter  = Backbone.Model;
var chapters = new Backbone.Collection;

chapters.comparator = function(chapter) {
  return -chapter.get("page"); // Note the minus!
};

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'));
Run Code Online (Sandbox Code Playgroud)

  • 请注意,仅当您的条件是数字时才有效. (43认同)
  • 自2012年初以来,支持排序式比较器.只需接受2个参数并返回-1,0或1. https://github.com/documentcloud/backbone/commit/6b3ff7b0359510917d9ead8c8e16a7457eef05ef (9认同)
  • hi5使用与我的相同的示例代码!,并在15秒内差异.像我一样,我必须说. (3认同)

And*_*ate 56

就个人而言,我对这里给出的任何解决方案都不满意:

  • 当排序类型为非数字时,乘以-1解决方案无效.虽然有办法解决这个问题(Date.getTime()例如通过调用),但这些案例是具体的.我想要一种通用的方法来反转任何类型的方向,而不必担心被排序的字段的特定类型.

  • 对于字符串解决方案,一次构造一个字符串似乎是性能瓶颈,尤其是在使用大型集合(或者实际上是大型排序字段字符串)时

这是一个适用于String,Date和Numeric字段的解决方案:

首先,声明一个比较器,它将反转sortBy函数的结果,如下所示:

function reverseSortBy(sortByFunction) {
  return function(left, right) {
    var l = sortByFunction(left);
    var r = sortByFunction(right);

    if (l === void 0) return -1;
    if (r === void 0) return 1;

    return l < r ? 1 : l > r ? -1 : 0;
  };
}
Run Code Online (Sandbox Code Playgroud)

现在,如果你想颠倒排序的方向,我们需要做的就是:

var Chapter  = Backbone.Model;
var chapters = new Backbone.Collection;

// Your normal sortBy function
chapters.comparator = function(chapter) {
  return chapter.get("title"); 
};


// If you want to reverse the direction of the sort, apply 
// the reverseSortBy function.
// Assuming the reverse flag is kept in a boolean var called reverseDirection 
if(reverseDirection) {
   chapters.comparator = reverseSortBy(chapters.comparator);
}

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'));
Run Code Online (Sandbox Code Playgroud)

这样做的原因是,Backbone.Collection.sort如果sort函数有两个参数,那么行为会有所不同.在这种情况下,它的行为方式与比较器的传入方式相同Array.sort.此解决方案通过将单个参数sortBy函数调整为两个参数比较器并反转结果来工作.

  • 作为对这个问题有最好的回答的人,我真的很喜欢这种方法,并认为它应该有更多的赞成. (7认同)

And*_*ade 46

Backbone.js的集合比较器依赖于Underscore.js方法_.sortBy.sortBy实现的方式最终以一种使反向排序字符串变得困难的方式"包装"javascript .sort().简单地否定字符串最终返回NaN并打破排序.

如果你需要使用字符串执行反向排序,例如反向字母排序,这是一种真正的hackish方式:

comparator: function (Model) {
  var str = Model.get("name");
  str = str.toLowerCase();
  str = str.split("");
  str = _.map(str, function(letter) { 
    return String.fromCharCode(-(letter.charCodeAt(0)));
  });
  return str;
}
Run Code Online (Sandbox Code Playgroud)

它绝不是漂亮的,但它是一个"字符串否定者".如果您对javascript中的本机对象类型没有任何疑虑,可以通过提取字符串否定符并将其作为String.Prototype上的方法添加来使代码更清晰.但是,如果您知道自己在做什么,可能只想这样做,因为在javascript中修改本机对象类型会产生无法预料的后果.


小智 28

我的解决方案是在排序后反转结果.

要防止双重渲染首先使用静音排序,然后触发"重置".

collections.sort({silent:true})
collections.models = collections.models.reverse();
collections.trigger('reset', collections, {});
Run Code Online (Sandbox Code Playgroud)

  • 丹尼尔,这并不总是可行的,例如在排序字符串或日期时. (7认同)
  • 更好的解决方案是否定比较器的结果. (2认同)

Dhr*_*hak 13

修改比较器函数以返回一些反向的proporitional值,而不是返回您当前的数据.一些代码来自:http://documentcloud.github.com/backbone/#Collection-comparator

例:

var Chapter  = Backbone.Model;
var chapters = new Backbone.Collection;

/* Method 1: This sorts by page number */
chapters.comparator = function(chapter) {
  return chapter.get("page");
};

/* Method 2: This sorts by page number in reverse */
chapters.comparator = function(chapter) {
  return -chapter.get("page");
};

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"}));
Run Code Online (Sandbox Code Playgroud)


rbh*_*ock 9

以下对我有用:

comparator: function(a, b) {
  // Optional call if you want case insensitive
  name1 = a.get('name').toLowerCase();
  name2 = b.get('name').toLowerCase();

  if name1 < name2
    ret = -1;
  else if name1 > name2
    ret = 1;
  else
    ret = 0;

  if this.sort_dir === "desc"
    ret = -ret
  return ret;
}

collection.sort_dir = "asc";
collection.sort(); // returns collection in ascending order
collection.sort_dir = "desc";
collection.sort(); // returns collection in descending order
Run Code Online (Sandbox Code Playgroud)


Fas*_*ani 8

我读了一些Backbone比​​较器函数使用或模仿JavaScript Array.prototype.sort()函数的地方.这意味着它使用1,-1或0来决定集合中每个模型的排序顺序.这会不断更新,并且基于比较器,收集将保持正确的顺序.

可以在此处找到有关Array.prototype.sort()的信息:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort? redlocol = en-US&redctsctsgg = JavaScript%2FReference%2FGlobal_Objects%2FArray%2Fsort

关于这个问题的许多答案只是在将其交给页面之前反转顺序.这不太理想.

使用上面的Mozilla文章作为指南,我能够使用以下代码以相反的顺序对我的集合进行排序,然后我们只是将集合呈现为页面的当前顺序,我们可以使用标志(reverseSortDirection)来反转顺序.

//Assuming this or similar will be in your Backbone.Collection.
sortKey: 'id', //The field name of the item in your collection

reverseSortDirection: false,

comparator: function(a, b) {

  var sampleDataA = a.get(this.sortKey),
      sampleDataB = b.get(this.sortKey);

      if (this.reverseSortDirection) {
        if (sampleDataA > sampleDataB) { return -1; }
        if (sampleDataB > sampleDataA) { return 1; }
        return 0;
      } else {
        if (sampleDataA < sampleDataB) { return -1; }
        if (sampleDataB < sampleDataA) { return 1; }
        return 0;
      }

},
Run Code Online (Sandbox Code Playgroud)

比较器除了两个模型,对集合或模型的更改运行隔离函数并更改集合的顺序.

我用Numbers和Strings测试了这种方法,它对我来说似乎很有效.

我真的希望这个答案有所帮助,因为我多次努力解决这个问题,并且通常最终会使用一种解决方法.


Ama*_*jan 5

这可以通过重写sortBy方法来优雅地完成.这是一个例子

var SortedCollection = Backbone.Collection.extend({

   initialize: function () {
       // Default sort field and direction
       this.sortField = "name";
       this.sortDirection = "ASC";
   },

   setSortField: function (field, direction) {
       this.sortField = field;
       this.sortDirection = direction;
   },

   comparator: function (m) {
       return m.get(this.sortField);
   },

   // Overriding sortBy (copied from underscore and just swapping left and right for reverse sort)
   sortBy: function (iterator, context) {
       var obj = this.models,
           direction = this.sortDirection;

       return _.pluck(_.map(obj, function (value, index, list) {
           return {
               value: value,
               index: index,
               criteria: iterator.call(context, value, index, list)
           };
       }).sort(function (left, right) {
           // swap a and b for reverse sort
           var a = direction === "ASC" ? left.criteria : right.criteria,
               b = direction === "ASC" ? right.criteria : left.criteria;

           if (a !== b) {
               if (a > b || a === void 0) return 1;
               if (a < b || b === void 0) return -1;
           }
           return left.index < right.index ? -1 : 1;
       }), 'value');
   }

});
Run Code Online (Sandbox Code Playgroud)

所以你可以像这样使用它:

var collection = new SortedCollection([
  { name: "Ida", age: 26 },
  { name: "Tim", age: 5 },
  { name: "Rob", age: 55 }
]);

//sort by "age" asc
collection.setSortField("age", "ASC");
collection.sort();

//sort by "age" desc
collection.setSortField("age", "DESC");
collection.sort();
Run Code Online (Sandbox Code Playgroud)

此解决方案不依赖于字段类型.