Backbone. Почему collection.reset не вызывает событие модели?

Мне любопытно узнать, почему сброс базовой коллекции не запускает событие модели. Однако кажется логичным запускать событие модели, когда модель физически удаляется из коллекции.

Это намеренно или я что-то упускаю? Если магистраль не делает такого рода вещи, что является хорошей практикой для делегирования подобных событий.

Почему магистраль не запускает событие модели при сбросе коллекции?

var TicketModel = Backbone.Model.extend({
    defaults: {
        name: 'crafty',
        email: '[email protected]'
    },
    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();

person Julian Krispel-Samsel    schedule 02.08.2012    source источник
comment
достаточно справедливо, если это проясняет, спасибо rimian   -  person Julian Krispel-Samsel    schedule 02.08.2012


Ответы (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 строки, потому что вы не предоставляете никаких моделей для функции сброса. Также давайте проигнорируем первые 2 строки. Итак, сначала мы перебираем модели в этой коллекции и вызываем метод коллекции _removeReference(model), он выглядит так:

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

Здесь происходит то, что мы полностью удаляем свойство коллекции из объекта модели, а также удаляем привязку к событиям этой модели. Затем мы вызываем _reset()-функцию коллекции, которая выглядит так:

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

Он просто полностью удаляет любые ссылки на любые модели, которые когда-либо были в коллекции.

Что мы можем сделать из этого? Что ж, функция сбора reset в Backbone в основном просто обходит все официальные каналы удаления моделей и делает все это в полной секретности, не вызывая никаких других событий, кроме 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;
  }
});

Надеюсь это поможет!

person jakee    schedule 02.08.2012
comment
очень обстоятельный ответ. И читать тоже приятно! Большое спасибо! - person Julian Krispel-Samsel; 02.08.2012
comment
нет проблем, это всегда отличный опыт изучения исходного кода, чтобы найти решение для такого вопроса! - person jakee; 02.08.2012
comment
Интересно, что за этим стоит. Модели «удаляют» события, всплывающие в коллекции, так почему бы не наоборот? - person Julian Krispel-Samsel; 02.08.2012
comment
Я разместил вопрос здесь, кто знает, может быть, мы получим немного справочной информации о том, почему модели не знают о поведении своей коллекции. github.com/documentcloud/backbone/issues/1521 - person Julian Krispel-Samsel; 02.08.2012

Переопределение метода Backbone может вызвать проблемы при обновлении до другой версии.

Backbone хранит массив моделей до сброса в options.previousModels, поэтому просто прослушайте событие сброса и вызовите событие «удалить» для этих предыдущих моделей:

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

Это поможет.

person Julian Krispel-Samsel    schedule 08.02.2013