Need help?

I'm available for remote short term contracting or consultancy work. Please check out my LinkedIn profile for more details on my experience.

Please feel free to use the form below to contact me.




Managing Views on Backbone JS

If you’ve had the pleasure of building large applications with Backbone.js, then you probably stumbled into this problem. What happens to Views that are no longer being used? That’s the main question.

Let me give you a test scenario - what if you have your main container (a div), and that container will be populated by View content. Every time the user navigates to a new section, that main container’s content will be swapped with a new View. What happens to the old view? Well, it will be sitting there still. Can’t we just hide it, you say? Well, yeah, but then it’s still rendering all the events, based on Model changes (if it has Models bound to it).

The best option is to manage our own clean-up, and destroy Views that are no longer being used. There is the other argument, that the garbage collection will clean-up the View as soon as the variable reference no longer exists; but for a massive system, you are wasting a lot of cycles. As you’re waiting for it to be cleaned up, your Models can be constantly changing, which could trigger countless events on those dead Views.

Here is an example Backbone Controller, which will demonstrate how we can control the Views.


(function () {
    // here we create a reference to the container on the page (and yes we are using jQuery as well)
    var $container = $("#container");
    // keeping a reference to the current active view
    var currentView = null;
    
    // lets create the controller
    var MainController = Backbone.Controller.extend({
        // if you notice, we’re using ‘!’ - this is actually going to look like this ‘#!’, and it’s called a hash-bang. These are a lot more SEO friendly in Google’s eyes.
        routes: {
            "!/" : "home",
            "!/connections" : "connections"
        },
        
        initialize: function(){
            // init all the models and collections
        },

        connections: function() {
            // destroy currentView, and then set it to the new one
	currentView.destroy();
            
            currentView = new ConnectionsView();
            $container.empty();
            $container.html($(currentView.el));
        }
    });

    var accountController = new AccountController();
    Backbone.history.start();
})();


If you’ve used Backbone for a bit, then most of that probably looks familiar, if not terribly obvious/easy. You must be wondering where the destroy() method came from. That’s actually a custom method, which I created in a Global View - this GlobalView gets inherited by all the other views, and therefore inheriting destroy().

Here’s what the GlobalView looks like:


GlobalView = Backbone.View.extend({    
    // removes this view to free up memory
    destroy: function(){
        this.remove();
    }
});

Real simple right? All that does is just remove the DOM content. You will need to extend that destroy() functionality on each View, and unbind any events/bindings as well. Here is the ConnectionView example:


ConnectionsView = GlobalView.extend({
    tagName: 'div',
    
    initialize: function(){
        this.render();
    },
    
    render: function(){
        // Compile the template using underscore
        var template = _.template($("#connections-template").html(), {});
        // Load the compiled HTML into the Backbone "el"
        $(this.el).html(template);
    },
    
    destroy: function() {
        GlobalView.destroy();
        
        // here we can unbind stuff
        // backbone.js renamed bind and unbind to on and off, just to follow suit with jQuery I guess
        // object.off("change", render);
    }
});


That view creates an anonymous div, which we use to store the View content. And as you can see, it overrides the destroy method, and do any clean-up that’s necessary.

Hope this helps someone, and if you notice any mistakes, please let me know.


jon | June 02, 2012 | Comments (0)

Comments


Name (required)
Email (will not be published) (required)
Website

captcha