简体   繁体   English

Backbone - 为什么collection.reset不会触发模型事件?

[英]Backbone - Why doesn't a collection.reset trigger a model event?

I'm curious to find out why resetting a backbone collection doesn't fire a model event. 我很想知道为什么重置骨干集合不会触发模型事件。 However, it seems only logical to fire a model event when a model is physically being removed from a collection. 但是,在从集合中物理移除模型时触发模型事件似乎是合乎逻辑的。

Is this intentional or am I missing something? 这是故意还是我错过了什么? If backbone doesn't do this sort of thing what's a good practice for delegating events like so. 如果骨干不做这种事情,那么委托事件就是一个很好的做法。

Why does backbone not trigger a model event when its collection resets? 为什么骨干在其集合重置时不会触发模型事件?

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

This is the backbone reset function: 这是骨干重置功能:

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

We can ignore the last 3 lines because you don't supply any models to the reset-function. 我们可以忽略最后3行,因为你没有为reset-function提供任何模型。 Also let's ignore the first 2 lines as well. 我们也要忽略前两行。 So first we loop through the models in this collection and call the collection's _removeReference(model) method, it looks like this: 首先,我们遍历此集合中的模型并调用集合的_removeReference(model)方法,它看起来像这样:

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

What happens here is that we're removing the collection-property from the model object altogether and also remove the binding to this model's events. 这里发生的是我们完全从模型对象中删除collection-property,并删除对该模型事件的绑定。 Next up we call the collection's _reset() -function, that looks like this: 接下来我们调用集合的_reset()函数,如下所示:

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

It just outright removes any reference to any models the collection has ever had. 它只是彻底删除了对该系列曾经拥有的任何模型的任何引用。

What can we make from this? 我们能从中做出什么? Well the collection reset -function in Backbone basically just circumvents all the official channels of removing models and does it all in hush hush secrecy, causing no other events than reset to be fired. Backbone中的集合reset功能基本上只是绕过了所有官方删除模型的渠道,并且在嘘声保密的情况下完成所有操作,导致除了reset之外没有其他事件被触发。 So you want to fire the model's remove event for every model removed from a collection during reset? 因此,您希望在重置期间为从集合中remove的每个模型触发模型的remove事件? Easy! 简单! Just overwrite Backbone.Collection's reset-function like this: 只需覆盖Backbone.Collection的reset-function,如下所示:

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

Hope this helps! 希望这可以帮助!

Overriding Backbone method can cause pain when updating to another version. 更新到另一个版本时,重写Backbone方法会导致痛苦。

Backbone stores an array of the models before the reset in options.previousModels, so just listen to the reset event and trigger a 'remove' event on those previous models: Backbone在options.previousModels中重置之前存储了一组模型,因此只需监听reset事件并在之前的模型上触发'remove'事件:

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

That'd do the trick. 那就是诀窍。

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

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