【问题标题】:Backbone.js: correct way of filtering a collection?Backbone.js:过滤集合的正确方法?
【发布时间】:2012-08-06 20:50:11
【问题描述】:

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

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

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

谢谢

【问题讨论】:

  • 你有什么理由不只使用fetch({add: true}) 而不是重置?听起来这就是您想要实现的目标。我不确定你的 filter 函数在做什么,但你也可以随时传递 {data : {...}} 来获取。
  • 如果我理解正确,您希望我完全删除 originalCollectionArray 及其事件,并在每次进行过滤/排序时获取原始数据(排序对过滤后的数据执行,因此每次排序也需要获取和过滤)?问题是,过滤器是在用户输入时触发的。我认为这会浪费太多资源。不过,我只是假设性地谈论。

标签: collections backbone.js


【解决方案1】:

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

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

无论您应用什么过滤器,父集合都会保留其模型,并且您绑定到过滤后的集合以了解何时发生更改。在 add 和 remove 事件上进行内部绑定可让您重新应用过滤器。看 http://jsfiddle.net/dQr7X/ 进行演示。

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-03-12
      • 1970-01-01
      • 2011-10-27
      • 1970-01-01
      • 1970-01-01
      • 2014-08-20
      • 1970-01-01
      相关资源
      最近更新 更多