jashkenas / backbone

Give your JS App some Backbone with Models, Views, Collections, and Events
http://backbonejs.org
MIT License
28.1k stars 5.39k forks source link

Should `stopListening` call `off` aswell? #4187

Closed ogonkov closed 2 years ago

ogonkov commented 6 years ago

Just discovers, that stopListening actually clears only child listeners.

If view listens some other objects (ie models/collections), it would be cleared.

But if i have some custom controller, that listens view, that listener would not be cleaned. Is it intended behaviour?

function FooController(options) {
  this.init(options);
}

FooController.prototype.init = function(options) {
  this.listenTo(options.view, 'foo', 'do some stuff');
};

Object.assign(FooController.prototype, Backbone.Events);

var view = new Backbone.View();
var ctrl = new FooController({view: view});

view.remove(); // At this point `ctrl` still have references to `view`

https://jsfiddle.net/ogonkov/08k3mecr/1/

I should somehow call FooController#stopListening manually, when view get destroyed?

I was sure that one of the advantages of using listenTo is automatic cleaning up of all listeners from object, when it gets removed. o_O

jaapz commented 6 years ago

What's this in your controller? listenTo and stopListening are only called "automatically" for views because of their lifecycle. listenTo itself does not know when it should stop listening again, the view explicitly calls stopListening when it is destroyed. Your controller does no such thing

ogonkov commented 6 years ago

I have updated my example, to make it more clear.

The question is: why removed object didn't clean it listeners in parent object? I thought that it should work this way, but it's clean only listeners to objects, that it listen to.

jaapz commented 6 years ago

view.remove only removes event listeners that the view itself made (through view.listenTo), not the event listeners other objects made on that view. If you want to remove the event listeners that are attached to the controller, you need to call ctrl.stopListening() before view.remove().

jgonggrijp commented 2 years ago

You are mixing up the .on and .listenTo methods. Use .on if the Listening object outlives the triggering object. Use .listenTo if the triggering object outlives the listening object. If you follow this rule, event bindings will be automatically cleaned up in all cases.