Reflections on Using Backbone.js

JavaScript frameworks like Backbone.js can provide the structure missing in ad hoc approaches but there are some common pitfalls.

Like many developers today my first professional experience with JavaScript was using jQuery. I began with minor enhancements to pages and forms however with each project, my use of JavaScript increased until the lack of organization and number of lines of code began to create problems. Those problems were not insurmountable but I began to look at other options and became interested in Backbone.js.

From the Backbone.js website:

Backbone.js gives structure to web applications by providing models with key-value binding and custom events, collections with a rich API of enumerable functions, views with declarative event handling, and connects it all to your existing API over a RESTful JSON interface.

Along with those features, the source code is annotated and currently totals 1533 lines in length for the legible development version (typically, JavaScript libraries are minified for production).

What brought me to Backbone.js was MVC. I was familiar with the architectural approach from using ASP.NET MVC and Ruby on Rails. What I was not prepared for was some of the pitfalls.

Pitfall: Duplicate Event Binding

Creating the first view is simple. For example, we could have a form like this one:

<form id="my-form">
    <label for="firstname">First name</label>
    <input id="firstname" class="attribute" name="firstname" />
    
    <input class="submit" type="submit"/>
</form>

And a view:

var View = Backbone.View.extend({
    el: '#my-form',

    events: {
        'click .submit': 'submit'
    },

    submit: {
        ...
    }
});

Creating an instance of View binds it up to the form and it works great. However at some point you may create another instance of the View. A common example is the view-update cycle: one view shows the data and another presents it in editable form. After updating, one typically views the data again. If another instance of the View is created the events will be bound twice. And each cycle of view-update will create yet another binding. This is a problem because if the submit event of the form is bound to sending an update to the server it will then send multiple updates. Here is an example of this problem on jsFiddle:

Enter "Bob" for first name and submit: A single event binding.

Now create another instance of the view by clicking on "Instantiate View" and enter another name: Duplicate event bindings.

What this demonstrates is that one has to be careful when creating instances of views. If while debugging you notice duplicate AJAX submissions, you now know what the likely problem is!

Pitfall: State as DOM Attributes

Before I started using a client-side MVC framework, I sometimes stored state in the DOM as data attributes. The data-* attributes were introduced with HTML5 and at first glance it seems like an ideal way to store data. However this becomes problematic when one uses an MVC framework as almost by definition one is going to have multiple views for a single object. Using data-* attributes tightly binds us to the DOM which requires a trip to the DOM for any change. Attempting to minimize this means we may get out of sync with the DOM.

Pitfall: Views That Instantiate Other Views

At a higher level, one of the causes of duplicate event bindings is views that instantiate other views. It can be tempting to tie together CRUD functionality so one can edit one item in a list of items without re-rending the whole list. But as soon as one begins to take this path, the risk of duplicate event bindings rises. Be very careful.

Recommended Resources

Cymen Vig enjoys working on complex client-side JavaScript projects and traveling with his wife Robin.