Before I introduce you to Backbone.js lets have some overview about Single Page Applications (SPA). SPA is a trend that is being widely followed while developing large, complex, yet scalable and high performance web apps. Google’s Gmail is a great example of single page app, and having used it at least once, we all can say that “Yes, it’s different!”. In SPA we separate out the logic for interface and data, and a central component that manages communication between these two. This technique is further termed as Model View Controller pattern i.e. MVC. So does it sound exciting to build a single page app? Definitely yes. But building something without any structure is a bad idea. The problem is, standard JavaScript libraries such as jQuery, MooTools etc. are great at what they do but without having any architecture or pattern your application may end up with piles of jQuery callbacks all tied to concrete DOM elements. Backbone.js transforms your application into well structured, modular and scalable app.
Now let’s see the components of Backbone in details.
What’s inside Backbone?
Backbone is an incredibly small library for the amount of functionality and structure it gives. It provides you an essential MVC core and makes your application modular. It also enforces that communication to server is always done via REST APIs, which reduces the need of manual AJAX calls to server. It works with only one dependency ie. Underscore.js. Underscore.js is an independent package of many useful utility functions written over plain JavaScript. So here are the key players from team Backbone:
Model
Models are the heart of any MVC application,that contains all the interactive data as well as large part of the logic surrounding around it. That logic contains conversions, validations, computed properties and access control.
Here we have created a model definition with default values and a method to mark mail as read. Then we created a model instance with property “to” with an email id which is a string. Model properties are not defined like a schema as we do in databases, since it’s a JavaScript, object properties can be defined at any time. Backbone model provides many other benefits such as:
- Events on model that provides ability to bind various functionality over them, various in built events supported such as add, remove, change, sync, destroy etc.
- Interacting with server over HTTP REST APIs.
Model takes an endpoint URL and communicates with server via REST calls i.e. GET, POST, PUT & DELETE. This is done with methods exposed by model such as fetch, save, destroy and sync.
Backbone model supports data bindings directly to DOM elements. This reduces the pain of passing data to visual elements but Backbone supports only one way data-binding. But don’t worry there are several open source libraries which supports two way data bindings and templating which is fully compatible with Backbone models such as Rivets.js, this is something like icing on the cake.
View
Backbone View is presentation logic which handles user interfacing. It renders the HTML templates, binds model’s data on it and supports user interactions via events. When a view is instantiated it creates it’s visual elements wrapped into an element i.e. “el” property. It is then returned or appended to DOM using it’s “render” method. All events scoped in current view are bound to DOM as specified in “events” property. Backbone View is fully compatible and it recommends using Underscore library for templates and jQuery for events. So let’s create a view to display single mail, with a button to close this view. Here binding to close button is provided in “events”, when its’ delegate “closeMail” is called we use remove method view to remove it from DOM. “initialize” is fired whenever instance of view is created. We call “render” method which then creates a view visuals by template and model, and finally puts HTML on $el, i.e. jQuery wrapped “el”.
To avoid all manual render, and have automatic garbage collection of Backbone views and events there is an add-on framework already created, known as Marionette.js. Marionette is a collection of common design implementation patterns required for large scale composite web applications.
Router
Backbone Router is responsible for navigation in your application using # part of the URL. Router is useful when application has many features separated with views and there is a need to navigate them with identical URLs. Router maps the URL pattern and corresponding function to handle the request, so being on the same page usually the practice of removing old views and creating new one to display intended screen is followed here. Let’s have quick example of this.
As per router configuration above,
URL index.html#mails/inbox - it opens inbox
URL index.html#mails/write - this hides inbox and shows a view to write new mail.
Backbone router also supports dynamic parameters in URLs, which adds more capabilities to pass identical data to views and render data specific to that entity.
Eg. index.html#/inbox/1 – it opens single mail with id 1.
Collection
Backbone Collection comes in picture when we have list of data elements. Collection is an ordered set of models. It provides various useful operations on list by bunch of exposed methods such as: add, remove, get, set, sync, sort, where etc. Collection takes care of pagination of large data sets to provide better performance. It connects to server directly with REST endpoint and performs bulk operations with simply calling its methods.
This creates a collection of draft mails and “where” method filters out mails without subject.
Events
This great module can be used over any Backbone object. Events provide ability for objects to bind and trigger custom named events, these events do not have to be declared before they are bound, they also support passed arguments. These are the set of methods from Events object that provides these event-ing features: on, off, trigger, listenTo, stopListening etc.
mail_view.listenTo(mail,'change', mail_view.render); mainView.listenTo(mail_view,'mailClosed', mainView.refreshInbox);
First binding listens to “change” event from mail model and raises render method of mail_view View.
Second binding listens to custom event “mailClosed” from mail_view View and raises refreshInbox method of mainView View.
History
Backbone History is global router that monitors URL hash changes and raises callbacks based on module level routers inside application. Application might contain many instances of routers inside modules. So when all your routers are set up, call Backbone.history.start() to start monitoring URL hash change events and dispatching them to subscribed router.
How does Backbone help?
Using Backbone in your application provides some strong pillars in terms of Views, Models and Routers. These building blocks are used together make a platform to scale your application into large and composed app which can serve large numbers of modules and sub-modules. Events provide you a great way of messaging throughout the components. Using all these features in one single library keeps your code shorter and manageable. This is how Backbone supports you in building better apps. Actually not just “better” but cleaner, lightweight and structured apps.