New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix #1339 - Add Backbone.View#destroy. #1353
Conversation
If any implementation is to be provided, I think it should be very minimal. For instance: if (this.model) this.model.off(null, null, this);
if (this.collection) this.collection.off(null, null, this); |
I’m a strong supporter of adding these things to Backbone, at least as a convention. I have to admit I’m biased since I released a Backbone-based library which has a focus on object disposal and memory management. ;) In Chaplin, we’re using the name As an overview, Thorax is calling it freeze, Marionette is calling it close. While Thorax and Marionette are using an event unbinding abstraction, Chaplin is already using the How about paving the cowpaths here? |
I've called it 2 cents |
I too think that it makes sense to solidify this convention. I would lean towards a complete no-op to keep this as light as possible, but could see the case for the simple implementation posted above |
+1 on adding it with a base implementation rather than a no-op as it's very minimal and would likely be the most common use case (unlike render, which varies widely) |
@braddunbar any documentation to go along with this? IMO these stubbed in methods are only worthwhile if there are clear usage guidelines in the docs.. |
@wookiehangover Good point, fleshing out docs will probably be informative as to including or not including this. I'll do a draft. |
I just started using Backbone and came to a similar conclusion. I'm glad I'm not the only one. I went with Backbone.View.prototype.remove = function() {
this.teardown().$el.remove();
return this;
};
Backbone.View.prototype.teardown = function() {
return this;
}; Then I would just override |
I've added some initial documentation for the I think that adding some convention for destroying views has been unanimously approved so I'm going to merge this as is. However, please continue to comment or open issues regarding naming, implementation, or documentation. |
Fix #1339 - Add Backbone.View#destroy.
Along similar lines, I wrote Coccyx to provide teardown-able view hierarchies. The intent is to provide a way to plug up leaky view hierarchies: just Coccyx also monkey-patches .on and .off (I know, I know, awful... "but it works, and I wrote tests around it"). This allows all contextualized event bindings (not just bindings to |
I think |
@webbower jQuery cleans up all events bound with |
@tgriesser That's true, but not all views call |
Whoops -- I didn't realize this got merged in. Can we roll it back out of master, and discuss further? If we're going to standardize a "destroy" method for views, I think it might as well not be a |
@jashkenas some ideas for implementations of https://github.com/chaplinjs/chaplin/blob/master/src/chaplin/models/model.coffee#L78 |
Sure thing. Reverted in d8477f4. |
+1 for this as a non no-op, a default implementation doing We've standardized on |
Just wanted to create the same issue ... I am also using .destroy on views, collections and models. My destroys do the same thing supposed here earlier - unbinding all events the view/collection/model has listened to + .remove on views.
I have started to use destroy a long time ago, after the application started to get slower and slower. I started to investigate why. The reason was mostly views, which have been removed from the dom, but still listened to the events from collections/models and has processed/rendered stuff in stealth mode. So it is a real issue with real use cases. Everybody should use destroy and be warned to use it in the documentation. +100 for .destroy on everything. |
Think about socket.io which can be used in collection/models .. it will listen on events and views will react on them the whole time. Switching views by removing the previous one will create an endless amount of event handlers rendering stuff behind the scenes. |
jQuery is unbinding events from dom elements being removed via jquery. Backbone should follow the similar logic. |
Something like this + current Model#destroy logic for model.
|
@kof I'd imagine the majority of the memory leaks you're seeing could be fixed by using listenTo and stopListening instead of |
@akre54 thanks for the info about View#remove, I also completely forgot about listenTo, because I am still using 0.9.2 version. I just read some issues discussing why listenTo was introduced ... but I still not liking it. Its not nicely looking and inconsistent. |
@kof |
ok right, listenTo seems to be really the most clear way ... I have played with the idea to define more default namespaces like 'models, collections, views' etc. and unbind all events from them on remove/destroy, but it isn't very intuitiv if instantiating something new inside of a view f.e.. Also introducing an array where you need to put everything you listen to in order to stop listening on remove/destroy could be an option. |
off topic ... but
|
Hey @kof,
|
@akre54 @mponizil do you know any use cases, where after a view/model has been destroyed, somebody who was listening on it should still receive any events? The problem is now - we have no "destroy". So actually View#remove does too much now, If I just want to remove a view from the dom and insert it somewere else, I will need to add listener again. Same for $el.remove() of jquery. It seems to me if we want to clearly separate "remove/detach" from complete "destroy" we need this "destroy" thing. |
@mponizil also there should be 'remove' event on the view if other listeners should stop listening to the view on remove. |
Also there is no real conflict with current Model#destroy implementation. Current Model#destroy just should accept an options.sync and only if its true, send the 'delete' event. Otherwise just do the cleanups. |
As stated in #1339,
destroy
is a fairly strong convention as this point. Should Backbone reinforce this convention or leave it to the user? If so, I'm of the opinion that it should be left blank so that the user can fill it in. Even the most minimal default implementation would have drawbacks and make assumptions about the structure of the user's code.