Reputation: 222
I'm building a website in Backbone, and the site structure resembles that of Youtube, in that when you change pages using on-page links, only a portion of the DOM (i.e. the non-navigational components) is reloaded instead of the whole document.
Hence, when a user visits a subpage using a link on my site, Backbone will issue an AJAX call and receive the HTML for the subpage, which will look something like this:
<section id="SubpageView">...</section>
<script>
// Defines the view that controls #SubpageView.
if(typeof SubpageView !== 'undefined') {
// If this is the first time the page is loaded, create class.
var SubpageView = Backbone.Model.extend({
el: '#SubpageView',
...
});
}
MainView.currentSubpage = new SubpageView();
</script>
Is any downside (i.e. zombie views, memory leaks, etc.) to calling SubpageView() multiple times? It seems to me like defining a View element using el instead of tagName is for elements that you use only once.
Note: I'm aware that single-page web apps usually have all their templates baked into the persistent DOM, and all HTML is handled using client-side templating. But because I'm designing the site to degrade to traditional server-side rendering without pushState() or when Javascript is disabled, I don't want to bake all my templates into the persistent DOM.
Upvotes: 1
Views: 359
Reputation: 3819
This is a great question - I think a lot of people overlook this issue and it causes problems. "Zombie Views" is a great descriptor. I'd say you are right they can cause problems:
That last point is particularly important if you use Backbone's events hash, like:
events: {
'click .someButton': 'someMethod',
// ...
},
Since you are reusing the el
selector (as I think you should), the events of all the zombie views will stay active, and trigger the functions of the views when they are not meant to. This could mean duplicate behaviour, or other completely unexpected results.
As for the solution, I think you have two options: One would be to destroy your old view instances before updating. The default remove
method actually removes the el
, which you don't want... undelegateEvents
may help. Backbone doesn't really have a clean way to do what's required, so you'll end up writing a bit of code yourself.
I think a better option is to reuse your existing view instance with new data (collection
, model
, other instance data, or whatever is appropriate).
When you change the subview of your page, you are likely passing in some variable, say the fetched html:
$.get('/templates/someView.html', function(html) {
Mainview.currentSubpage = new SubpageView(html);
});
... or something like that. Instead, I'd recommend writing in a method to update an existing instance instead, like:
$.get('/templates/someView.html', function(html) {
Mainview.currentSubpage.resetPage(html);
});
where you write the resetPage
method into your SubpageView
to do just what you need. This could apply to a lot more than just passed in html of course, I'm just using that as an example.
Upvotes: 3