Backbone.js:过滤集合的正确方法?

时间:2012-08-09 15:20:03

标签: collections backbone.js

我正在使用的当前方法是过滤一个返回数组的集合,然后使用

collection.reset(array)

重新填充它。但是,这会修改原始集合,因此我添加了一个名为“originalCollectionArray”的数组,该数组跟踪集合的初始数组状态。如果没有过滤活动,我只需使用

collection.reset(originalCollectionArray)

但是,我需要跟踪从真实集合中添加和删除模型,所以我这样做了:

// inside collection
initialize: function(params){
    this.originalCollectionArray = params;
    this.on('add', this.addInOriginal, this);
    this.on('remove', this.removeInOriginal, this);
},
addInOriginal: function(model){
    this.originalCollectionArray.push(model.attributes);
},
removeInOriginal: function(model){
    this.originalTasks = _(this.originalTasks).reject(function(val){
        return val.id == model.get('id');
    });
},
filterBy: function(params){
    this.reset(this.originalCollectionArray, {silent: true});
    var filteredColl = this.filter(function(item){
        // filter code...
    });
    this.reset(filteredColl);
}

当我尝试实现与集合操作相关的其他技巧(例如排序)时,这很快变得很麻烦。坦率地说,我的代码看起来有点hacky。这样做有一种优雅的方式吗?

由于

2 个答案:

答案 0 :(得分:13)

您可以创建一个集合作为反映过滤器状态的主集合的属性:

var C = Backbone.Collection.extend({
    initialize: function (models) {
        this.filtered = new Backbone.Collection(models);
        this.on('add', this.refilter);
        this.on('remove', this.refilter);
    },

    filterBy: function (params){
        var filteredColl = this.filter(function(item){
          // ...
        });

        this.filtered.params = params;
        this.filtered.reset(filteredColl);
    },

    refilter: function() {
        this.filterBy(this.filtered.params);
    }
});

父集合将其模型保留为您应用的任何过滤器,并绑定到过滤后的集合以了解何时发生更改。通过添加和删除事件内部绑定,您可以重新应用过滤器。看到 http://jsfiddle.net/dQr7X/进行演示。

答案 1 :(得分:1)

您的代码的主要问题是您使用原始数组而不是Collection。我的代码与您的代码很接近但仅使用集合,因此添加,删除和过滤等方法适用于原始代码:

  var OriginalCollection = Backbone.Collection.extend({
  });
  var FilteredCollection = Backbone.Collection.extend({
    initialize: function(originalCol){
        this.originalCol = originalCol;
        this.on('add', this.addInOriginal, this);
        this.on('remove', this.removeInOriginal, this);
    },
    addInOriginal: function(model){
        this.originalCol.add(model);
    },
    removeInOriginal: function(model){
        this.originalCol.remove(model);
    },
    filterBy: function(params){
        var filteredColl = this.originalCol.filter(function(item){
            // filter code...
        });
        this.reset(filteredColl);
    }   
  });