【问题标题】:Backbone - Why doesn't a collection.reset trigger a model event?Backbone - 为什么 collection.reset 不触发模型事件?
【发布时间】:2012-07-31 06:19:32
【问题描述】:

我很想知道为什么重置主干集合不会触发模型事件。但是,当模型从集合中被物理删除时,触发模型事件似乎是合乎逻辑的。

这是故意的还是我遗漏了什么?如果主干不做这种事情,那么委派这样的事件是一个好习惯。

为什么主干在其集合重置时不触发模型事件?

var TicketModel = Backbone.Model.extend({
    defaults: {
        name: 'crafty',
        email: 'dwq@dwqcqw.com'
    },
    initialize: function(){
        this.on("all", function(event){
            console.log(event)
        });
    }

});

var TicketCollection = Backbone.Collection.extend({
    model: TicketModel,

    });


var tickets = new TicketCollection([
    {
        name: 'halldwq'
    },
    {
        name: 'dascwq'
    },
    {
        name: 'dsacwqe'
    }

]);

tickets.reset();

【问题讨论】:

  • 很公平,如果这样更清楚,谢谢 rimian

标签: javascript model-view-controller backbone.js backbone-events


【解决方案1】:

更新到另一个版本时,覆盖 Backbone 方法可能会导致痛苦。

Backbone 将重置前的模型数组存储在 options.previousModels 中,因此只需监听重置事件并在之前的模型上触发“删除”事件:

collection.on('reset', function(col, opts){
   _.each(opts.previousModels, function(model){
        model.trigger('remove');
    });
});

这样就可以了。

【讨论】:

    【解决方案2】:

    这是主干重置功能:

    reset: function(models, options) {
      models  || (models = []);
      options || (options = {});
      for (var i = 0, l = this.models.length; i < l; i++) {
        this._removeReference(this.models[i]);
      }
      this._reset();
      this.add(models, _.extend({silent: true}, options));
      if (!options.silent) this.trigger('reset', this, options);
      return this;
    },
    

    我们可以忽略最后 3 行,因为您没有为重置函数提供任何模型。也让我们忽略前两行。所以首先我们遍历这个集合中的模型并调用集合的_removeReference(model)方法,它看起来像这样:

    _removeReference: function(model) {
      if (this == model.collection) {
        delete model.collection;
      }
      model.off('all', this._onModelEvent, this);
    },
    

    这里发生的情况是,我们从模型对象中完全移除了集合属性,并且还移除了与该模型事件的绑定。接下来我们调用集合的_reset()-function,如下所示:

    _reset: function(options) {
      this.length = 0;
      this.models = [];
      this._byId  = {};
      this._byCid = {};
    }, 
    

    它只是彻底删除了对该集合曾经拥有的任何模型的任何引用。

    我们可以从中得到什么?好吧,Backbone 中的集合reset -function 基本上只是绕过了所有删除模型的官方渠道,并且完全保密,除了reset 之外没有其他事件被触发。所以你想为重置期间从集合中删除的每个模型触发模型的remove 事件?简单!只需像这样覆盖 Backbone.Collection 的重置函数:

    var Collection = Backbone.Collection.extend({
      reset: function(models, options) {
        models  || (models = []);
        options || (options = {});
    
        for (var i = 0, l = this.models.length; i < l; i++) {
          this._removeReference(this.models[i]);
          // trigger the remove event for the model manually
          this.models[i].trigger('remove', this.models[i], this);
        }
    
        this._reset();
        this.add(models, _.extend({silent: true}, options));
        if (!options.silent) this.trigger('reset', this, options);
        return this;
      }
    });
    

    希望这会有所帮助!

    【讨论】:

    • 非常彻底的答案。读起来也很愉快!非常感谢!
    • 没问题,通过源代码为此类问题找到解决方案总是一种很棒的学习体验!
    • 我想知道它背后的原因是什么。模型“删除”事件会冒泡到集合中,那么为什么不反过来呢?
    • 我在这里发布了一个问题,谁知道我们可能会得到一些背景信息,说明为什么模特不知道他们的收藏品的行为。 github.com/documentcloud/backbone/issues/1521
    猜你喜欢
    • 1970-01-01
    • 2012-02-11
    • 2013-09-28
    • 1970-01-01
    • 2021-07-16
    • 2011-12-03
    • 2014-12-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多