Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Backbone view DOM element removed

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!

like image 346
Cimm Avatar asked Dec 04 '22 06:12

Cimm


2 Answers

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!

like image 183
Alejandro Rubio Avatar answered Dec 14 '22 14:12

Alejandro Rubio


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.

like image 32
Sander Avatar answered Dec 14 '22 12:12

Sander