Marionette JS: правильно очистить ItemView при прослушивании других событий модели

Когда ItemView прослушивает модель, отличную от своей модели (this.model), нужно ли мне просто отключить прослушиватели в функции remove? И установить их ссылку на ноль? Интересно, будет ли безопасно уничтожен ItemView или у меня будут проблемы позже, когда будет создано/уничтожено множество таких представлений?

Пример :

var FriendListItemView = Marionette.ItemView.extend({
    [...]
    initialize: function(){
        Marionette.ItemView.prototype.initialize.apply(this, arguments);
        // get the friend and the user from global "users" collection
        this.user = users.get(this.model.get('user_id'));
        this.friend = users.get(this.model.get('friend_id'));
        this.user.on('change:name', this.render, this);
        this.friend.on('change:name', this.render, this);
    },
    remove: function(){
        this.user.off('change:name', this.render, this);
        this.friend.off('change:name', this.render, this);
        this.user = null;
        this.friend = null;
        Marionette.ItemView.prototype.remove.apply(this, arguments);
    },
});

person Simmoniz    schedule 02.09.2015    source источник


Ответы (2)


Вместо this.user.on('change:name', this.render, this); используйте функцию listenTo().

this.listenTo(this.user, 'change:name', this.render);

Marionette по умолчанию destroy вызывает remove из Backbone, который снова вызовет stopListening и удалит все прослушиватели событий, зарегистрированные через listenTo. Это должно сделать всю вашу функцию удаления ненужной. Подобные вещи — одна из проблем, о которых Marionette должна позаботиться за вас. Установка this.user и this.friends в ноль также не является ненужной.

person ivarni    schedule 02.09.2015
comment
Это именно то, что я искал. Хороший, полный и четкий ответ, спасибо ivarni! - person Simmoniz; 02.09.2015
comment
Из моих собственных тестов с использованием обозревателя Marionette, если вы вручную не вызываете this.model.destroy(); в onDestroy() модель никогда не уничтожается. - person Growiel; 21.01.2016
comment
@Growiel Мне бы хотелось увидеть демонстрацию такого поведения, поскольку я только что связался с исходным кодом, который явно вызывает эти методы. Может это более старая версия? - person ivarni; 21.01.2016

просто чтобы уточнить немного дальше. Метод destroy также будет запускать события и вызывать соответствующие методы. Кроме того, инициализация ItemView - это noop, поэтому нет причин вызывать прототип. Почти все имеет обработчики событий до и после, поэтому вам не нужно вызывать прототип.

var FriendListItemView = Marionette.ItemView.extend({
  [...]
  initialize: function(){
    // get the friend and the user from global "users" collection
    this.user = users.get(this.model.get('user_id'));
    this.friend = users.get(this.model.get('friend_id'));        
    this.listenTo(this.user, 'change:name' this.render);
    this.listenTo(this.friend, 'change:name' this.render);
  },
  onDestroy: function(){
    // you could do additional clean up here if you needed to
    // but you don't.  There's also an onBeforeDestroy
    // equivalent to this.on('destroy', this.doSomething);
  },
});
person Paul Falgout    schedule 04.09.2015