As far as I have been able to tell, listenTo
and stopListening
should replace on
and off
respectively. Do I understand that correctly? Is there any situation where on
/off
should be used instead of listenTo
/stopListening
?
Edit:
As I went to refactor my code, it became obvious that there are some cases for on
over listenTo
. The documentation is pretty clear that it is for when one object listens to another object:
Tell an object to listen to a particular event on an other object.
Therefore, when a collection
or model
is listening to an event on itself, we should use on
instead of listenTo
.
Assuming I have this correct...
The simple rule to follow is this:
Use listenTo
when listening for events on another object. Use on
when listening to events on self.
Copying an extract from an interesting blog post that I read recently. Hope it helps.
Avoiding common backbone pitfalls: Creating memory leaks by not unbinding events
A common pattern in Backbone.js is creating views that listen on changes in models or collections. This technique is usually intended to allow the view to automatically re-render itself when the underlying data changes. It also means that for large collections we may end up with many views (at least one for every model in the collection) that we may dynamically create or destroy based on changes to the data.
The problem arises when we remove a view (usually by calling its .remove() method), but forgetting to unbind the methods that listen on model changes. In such a case, even though our code may no longer hold a reference to that view, it is never garbage collected since the model still holds such a reference via the event handler.
Take this view for example:
var SomeModelView = Backbone.View.extend({
initialize: function() {
this.model.on('change', this.render, this);
},
render: function() {
// render a template
}
});
When calling the .remove() method, the "change" event handler (our render function) is still bound. So while the DOM element may be removed, the view object itself is never released from memory.
Solving this is easy (especially since Backbone 0.9.x) - all we need to do is to stop using .on() when binding the event handler. instead, we can use the new .listenTo() method, like this:
initialize: function() {
this.listenTo(this.model, 'change', this.render);
}
The biggest difference here being the shift in responsibility from the model to the view. This means that whenever we call .remove(), the view will automatically unbind any event bound to it using the .listenTo() method, essentially fixing this common leak.
For the most part, you understand it correctly. Here is a discussion on the matter from their github repository: https://github.com/documentcloud/backbone/issues/1923#issuecomment-11462852
listenTo
and stopListening
keep track of state. It will take care of cleanup for you at the cost of a little code overhead. In just about every case I can think of you'd want this behavior for your views, but you wouldn't be at fault for handling on/off calls yourself either; they won't be deprecating on
and off
any time soon.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With