4
votes

I keep reading about the Backbone.js zombie (or memory leak) problem. Basically you have to unbind and remove the element from the DOM when you no longer need it to make sure all events are removed as well.

Now, I have a single page app with a few containers:

<div id="page1"></div>
<div id="page2"></div>

and add my underscore.js templates to these placeholders. I have a model per page like:

HomeView = Backbone.View.extend({
  el: '#page1'
)}

Now, when I click on an element on that page I navigate to another Backbone.js view:

clicked: function(ev){
  $(this.el).remove(); // <-- this is the problem
  $(this.el).unbind();
  App.navigate('page/2', true);
}

This works fine but... I removed the page1 element from the DOM so when I use the back button to go to the previous page my element is gone and there is nothing to attach the HTML to.

I probably don't understand how to link Backbone.js views with the DOM... should I keep the element with the risk of memory leaks?

Thanks!

3
> I keep reading about the Backbone.js zombie (or memory leak) problem Got a link or article to back that up?Crescent Fresh
well derick does supply you with a solution does he not? a view manager or how you might want to call it.Sander

3 Answers

6
votes

As the article says, (yes, I've tried his methods before in my own projects), you have to find a way to remove your view's DOM element and unbind the events. There are, however, 2 types of events, 1) Backbone events, 2) the events that are bound to your DOM elements with jQuery.

So instead of your:

$(this.el).remove();
$(this.el).unbind();

Do this:

this.remove();
this.unbind();

You are now removing Backbone events as well; and the this.remove on a view will call $(this.el).remove();.

However, that is only how to remove a view and not leave zombies. You should consider his methods for showing a view to make this process more automatic. This is all in his article.

10
votes

In regard to losing the page1 element in your page, and therefore not being able to populate the item with HTML, I did the following.

Instead of using:

this.remove();

... which removes the element entirely, and then try to figure out how to add it back, I use jQuery's:

$(this).empty;

This empties all child elements, text, and data and event handlers. More info at: http://api.jquery.com/empty/

In fact, I use all of the following, which may be overkill but we'll see:

this.undelegateEvents();
$(this).empty;
this.unbind();

Hope this is useful!

1
votes

Backbone development version(master) now exposes _removeElement()

 remove: function() {
      this._removeElement();
      this.stopListening();
      return this;
    },

Remove this view’s element from the document and all event listeners attached to it. Exposed for subclasses using an alternative DOM manipulation API.

_removeElement: function() {
      this.$el.remove();
    },

http://backbonejs.org/docs/backbone.html