Backbone.js, a micro MVC for javascript

  • Laurent Prodon

Backbone.js is a small javascript MVC framework, developped and open-sourced by documentcloud.

context

We used backbone here at Liip for some small js projects (mobile and web), specially for a js game which was pretty easy UI wise but contained a lot of internal logic.

why MVC?

Usually the first question is ‘do you really need MVC for javascript?', and i guess there is no real answer to this
 The truth is that it helped us a lot in clarifying what to do and how to structure our application. As we all have a different background within the team (Php, Actionscript, Python) ‘speaking MVC' was a kind of common language.Anyway in most of js apps you'll need a router, and objects that act as models and views. Call it as you want
 it still looks a lot like MVC :)

why Backbone?

As said before we wanted a way to structure the javascript part of our apps. The goal was to have a tiny MVC layer that we could easily reuse and that would ease our life without too much overhead. And that's exactly what Backbone is!For us the main points of interest were that it provides: base components for both the views and models/collections a simple router (match url to function) with optional parameters an event mechanism for inter-components communication an easy way to update views on model modification scoping facilities (mostly through underscore.js which is the only pre-requisite for Backbone) template integration

how?

Templates

We used only 1 html file containing the base div structure and templates with placeholders. Backbone (via underscore.js) allows you to define templates like:

<script type="text/template" id="my-template">

    <div class="myclass-<%= id %>">

        <p><%= label %></p>

    </div>

</script>

You can then call the _template method with an Object as argument.. Nothing revolutionary, but quite helpful!

Structure

For the js part we first started with 1 js file containing everything (models, views, etc..) as presented in  the official example on backbone web page. This turned out to be not so maintainable as the file grew bigger and bigger, so we refactored to use 1 file for each logical part. In our case we had 1 for the ‘simulator' where computation were done, 1 for the router, 1 for the game logic, and several for the views. All those components were pseudo namespaced in an object that we called ‘app'.This led to a quite decoupled application with components that have a clear role and scope. Nice!

Events

Who says decoupled says communication, and here again Backbone helped us by providing an easy event system. For example, at first we had some concurrency problems on start up, so we decided to just trigger an event when all components are created. Something like:

// in main.js

// initialize all components here

this.trigger('ready');


// in any component

this.app.bind('ready', this.onReady);

onReady: function () {

    // do stuff

}

and with a little help of underscore.js we even can set the scope of ‘onReady' function as the component:

_.bindAll(this, 'onReady');

pretty easy huh?!It works the same for views which want to listen to model changes. By default models trigger some useful events like ‘change' or ‘error' (more on this afterwards) on value change. To set or get a value on/from a model you use:

this.model.get('key');

this.model.set({'key':'value', 'key2':'value'});

This has some added value: you can use the default model validator very easily:

// just override the validate function

validate: function(attrs) {

    // do custom validation based on passed attrs and return true if ok or any string ('not valid value')

}

Returning anything else then true will trigger an error event that you can catch in your view and handle as needed.

Router

The ‘controller' part in Backbone is a simple router. It allows you to map methods to urls, again very easily.

routes: {

    'main': 'mainHandler',

    'product/:id': 'productHandler'

},

productHandler: function(id) {

    // this will be called when /product/21 is reached, with of course id=21

}

There are a lot of other features in Backbone that i could talk about
 History management, sync with backend, all views methods, etc
 but hey! time for stĂŒtzbier :)NB: you can also find backbone and underscore.js in the microjs list. Happy coding!


Qu’en pensez-vous?