Javascript 使用 Backbone.js 反向排序

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5013819/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 15:15:03  来源:igfitidea点击:

Reverse sort order with Backbone.js

javascriptbackbone.js

提问by Drew Dara-Abrams

With Backbone.jsI've got a collection set up with a comparator function. It's nicely sorting the models, but I'd like to reverse the order.

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

How can I sort the models in descending order rather than ascending?

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

回答by Infeligo

Well, you can return negative values from comparator. If we take, for example, the example from Backbone's site and want to reverse the order, it will look like this:

好吧,您可以从比较器返回负值。例如,如果我们采用 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'));

回答by Andrew Newdigate

Personally, I'm not that happy with any of the solutions given here:

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

  • The multiplying by -1 solution fails to work when the sort type is non-numeric. Although there are ways around this (by calling Date.getTime()for example) these cases are specific. I would like a general way to reverse the direction of any sort, without having to worry about the specific type of the field being sorted.

  • For the string solution, constructing a string one character at a time seems like a performance bottleneck, especially when using large collections (or indeed, large sort field strings)

  • 当排序类型为非数字时,乘以 -1 的解决方案不起作用。尽管有解决此问题的方法(Date.getTime()例如通过调用),但这些情况是特定的。我想要一种通用的方法来反转任何排序的方向,而不必担心被排序的字段的特定类型。

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

Here's a solution that works nicely for String, Date and Numeric fields:

这是一个适用于字符串、日期和数字字段的解决方案:

Firstly, declare a comparator that will reverse the result of a result of a sortBy function, like this:

首先,声明一个比较器,它将反转 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;
  };
}

Now, if you want to reverse the direction of the sort, all we need to do is:

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

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'));

The reason this works is that Backbone.Collection.sortbehaves differently if the sort function has two arguments. In this case, it behaves in the same manner as the comparator passed into Array.sort. This solution works by adapting the single argument sortBy function into a two argument comparator and reversing the result.

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

回答by Andrew De Andrade

Backbone.js's collection comparator relies on the Underscore.js method _.sortBy. The way sortBy is implemented ends up "wrapping" up javascript .sort() in a way that makes sorting strings in reverse difficult. Simple negation of the string ends up returning NaN and breaks the sort.

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

If you need to perform a reverse sort with Strings, such as reverse alphabetical sort, here's a really hackish way of doing it:

如果您需要对字符串执行反向排序,例如反向字母排序,这里有一种非常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;
}

It's by no means pretty, but it is a "string negator". If you don't have any qualms with modifying native object types in javascript, you could make you code clearer by extracting the string negator and adding it as a method on String.Prototype. However you probably only want to do this if you know what you are doing, because modifying native object types in javascript can have unforeseen consequences.

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

回答by Tomasz Trela

My solution was to reverse results after sort.

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

To prevent double rendering first sort with silent, then trigger 'reset'.

为防止双重渲染,首先使用无声排序,然后触发“重置”。

collections.sort({silent:true})
collections.models = collections.models.reverse();
collections.trigger('reset', collections, {});

回答by DhruvPathak

Modify your comparator function to return some reversely proporitional value instead of returning the data that you are currently. Some code from : http://documentcloud.github.com/backbone/#Collection-comparator

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

Example:

例子:

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

回答by rbhitchcock

The following worked well for me:

以下对我来说效果很好:

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

回答by FMD

I read some where that the Backbone comparator function either uses or mimics the JavaScript Array.prototype.sort() function. This means it uses either 1, -1 or 0 to decide on the sort order of each model in the collection. This constantly updates and the collection stays in the correct order based on the comparator.

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

Info on Array.prototype.sort() can be found here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort?redirectlocale=en-US&redirectslug=JavaScript%2FReference%2FGlobal_Objects%2FArray%2Fsort

关于 Array.prototype.sort() 的信息可以在这里找到:https: //developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort?redirectlocale=en-US&redirectslug=JavaScript% 2FReference%2FGlobal_Objects%2FArray%2Fsort

Many answers on this question simply reverse the order just before rending it to the page. This is not ideal.

关于这个问题的许多答案只是在将其渲染到页面之前颠倒顺序。这并不理想。

Using the above article on Mozilla as a guide I was able to keep my collection sorted in reverse order using the following code, then we simply render the collection to page in it's current order and we can use a flag (reverseSortDirection) for reversing the order.

使用上面关于 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;
      }

},

Comparator except's two models, on changes to the collection or model the compartor function runs and changes the order of the collection.

比较器除了两个模型之外,在更改集合或模型时,比较器函数会运行并更改集合的顺序。

I have tested this approach with Numbers and Strings and it seems to be working perfectly for me.

我已经用数字和字符串测试了这种方法,它似乎对我来说很完美。

I really hope this answer can help as I have struggled with this problem many times and usually end up using a work around.

我真的希望这个答案能有所帮助,因为我曾多次与这个问题作斗争,并且通常最终会使用变通方法。

回答by Aman Mahajan

This can be done elegantly by overriding sortBy method. Here is an example

这可以通过覆盖 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');
   }

});

So you can use it like this:

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

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();

This solution does not depend on the field type.

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

回答by wprl

// For numbers, dates, and other number-like things
var things = new Backbone.Collection;
things.comparator = function (a, b) { return b - a };

// For strings
things.comparator = function (a, b) {
  if (a === b) return 0;
  return a < b ? -1 : 1;
};

回答by dezman

Here is a really simple solution, for those who simply want to flip the current order. It is useful if you have a table whose columns can be ordered in two directions.

这是一个非常简单的解决方案,适用于那些只想翻转当前订单的人。如果您有一个表的列可以按两个方向排序,这将很有用。

collection.models = collection.models.reverse()

You can combine it with something like this if you are interested in the table case (coffeescript) :

如果您对表案例(coffeescript)感兴趣,您可以将其与类似的内容结合使用:

  collection.comparator = (model) ->
    model.get(sortByType)

  collection.sort()

  if reverseOrder
    collection.models = collection.models.reverse()