简体   繁体   English

Backbone.js自定义集合排序

[英]Backbone.js custom collection sort

I have a Backbone.js app with marionette plugin. 我有一个带有marionette插件的Backbone.js应用程序。 There's a collection which renders with a CompositeView (and ItemViews) and I need to sort it in the following way: 有一个使用CompositeView(和ItemViews)渲染的集合,我需要按以下方式对其进行排序:

  1. User can rearrange rendered ItemViews (using jQuery sortable plugin) and this user preference gets saved in a cookie in a form of array of model IDs 用户可以重新排列渲染的ItemViews(使用jQuery可排序插件),并且此用户首选项以模型ID数组的形式保存在cookie中
  2. On each reload, I want to sort the fetched collection to be in the same order as this aforementioned array of user preference order. 在每次重新加载时,我想要将获取的集合排序为与上述用户首选项顺序数组相同的顺序。

I tried to sort collection.models array manually in the onRender hook and then re-rendering it, but this kind of collection manipulation just "feels wrong" (and causes an endless render loop). 我试图在onRender钩子中手动对collection.models数组进行排序,然后重新渲染它,但这种集合操作只是“感觉不对”(并导致无限的渲染循环)。

Is there some kind of a more elegant solution to sort a collection to have models in the same order as model IDs defined in some other array? 是否有某种更优雅的解决方案来对集合进行排序,使模型的顺序与其他数组中定义的模型ID的顺序相同?

Try to use Backbone.Collection#comparator method on collection which will access cookie with array of ids and uses it to return 1 or -1. 尝试在集合上使用Backbone.Collection#comparator method,它将使用id数组访问cookie并使用它返回1或-1。

comparator functions take two models, and return -1 if the first model should come before the second, 0 if they are of the same rank and 1 if the first model should come after. 比较器函数有两个模型,如果第一个模型应该在第二个模型之前返回-1,如果它们具有相同的等级,则返回0,如果第一个模型应该在之后,则返回1。

var MyCollection = Backbone.Collection.extend({

    comparator: function(model_a, model_b) {
        // In real app array comes from cookie
        var order = [5, 2, 1, 4, 3],
            a_index = order.indexOf(model_a.id),
            b_index = order.indexOf(model_b.id);

        if (a_index > b_index) {
            return 1;
        } else if (a_index < b_index) {
            return -1;
        } else {
            return 0;
        }
    }

});

var my_collection = new MyCollection([
    { id: 1 },
    { id: 2 },
    { id: 3 },
    { id: 4 },
    { id: 5 }
]);

alert(my_collection.pluck('id'));

Here is jsfiddle with this example 这是jsfiddle这个例子

One approach would be to map over your "custom" list of ids and return models in the collection with that id: 一种方法是映射您的“自定义”ID列表并使用该ID返回集合中的返回模型:

var items = [
  {id: 0, name: '1st', age: 40},
  {id: 1, name: '2nd', age: 50},
  {id: 2, name: '3rd', age: 60}
];

// order stored in cookie or localstorage ^^
var sorted = [2, 1, 0];

// our source collection
var collection = new Backbone.Collection(items);

// this could be implemented as a collection method if necessary
var sortedCollection = _.map(sorted, function (id) {
  return collection.get(id);
});


var sortedIds = sortedCollection.map(function (item) { return item.id })
console.log(sortedIds);
// [2, 1, 0]

jsbin with an example view jsbin以示例视图

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM