At the time of writing, apart from breezing through a few tutorials, I have not implemented anything with Backbone. I am making these notes as a reference overview of how Backbone works. When I get to D8 module development, if feasible, I may write a tutorial on how to incorporate Backbone into a Drupal module.
What it is
What is is not
Although it is often compared with popular frameworks and mistakenly called a framework, Backbone is not a framework; it is a library. It is also not a true MVC because it doesn’t have a controller. MV* would be more accurate.
The difference between frameworks and libraries
The terms framework and library are often used interchangeably but are conceptually different. The defining difference between the two is Inversion of Control.
A library is a collection of classes and functions that you call from your code. When you call a library from your code, you are in control. jQuery is a library. You call its functions from your code.
In a framework, the control is inverted. The framework calls your code and controls how your application is architected. A good example of a framework is Drupal. Via its hook system, it calls your custom code but flow control remains in Drupal. You can find an excellent discussion of libraries vs. frameworks in Martin Fowler’s Inversion of Control article referenced at the bottom.
Backbone.js, ReactJS and Knockout are libraries. AngularJS and Ember.js are frameworks. Libraries are more customizable than frameworks.
What it can do
The best way to gain an understanding of what Backbone can do is to explore how it is being used on live sites from the examples section of the Backbone home page. Most of the examples there are Single Page Applications but beware, many require you to register to explore their apps.
If you are code literate, reading the fully-commented version of the backbone.js source code is another good way to gain familiarity with how it works.
Why it is part of Drupal 8
Backbone has 4 core components: Model, View, Collection and Router.
Created using a namespace coding technique to prevent variable name conflicts by extending Backbone.Model, models contain application data as well as logic and behavior. They raise events when their state changes via the following methods:
initialize()- called when a new model instance is created. This is also a good place to add event listeners.
get()- gets a property of the model
set()- adds or updates a property of a model
on()- triggers model changes
save() - if called on a model, it uses the model’s id and the collection’s URL to create a new model via HTTP POST update the model on the server via HTTP PUT.
destroy() - removes a model from its collection and uses the collection’s URL to delete the model on the server with HTTP DELETE.
The Backbone.Model object also has a
validate() function that is called when
set() are fired.
Views are a visual representation of models but do not contain HTML markup. They contain the logic behind the model’s web page presentation. Created by extending Backbone.View, views usually observe models and are notified when the underlying models change. By displaying model data on the page, they tie the model and HTML page together by observing models and updating the user interface when changes occur. Views are dependent on one another and can communicate with one another. DOM events are handled by Views.
Since Views manage both the event handlers and DOM elements, they control all input and output on a Backbone-powered site.
el is short for element and can be thought of as the central property of a view because all views must have one. It is essentially a reference to a DOM element.
$el is a corresponding jQuery element that contains the
setElement can be used to apply an existing Backbone view to a different DOM element. setElement will create a cached el reference for you and move the delegated events for a view from the old element to the new one.
change() event, the view can instantly reflect model changes without a page refresh.
There are several other functions available for managing views elements.
Controller - The controller acts as a bridge between the model and view. It handles clicks and other user actions from the view, updates models and transports model data back to the view so it can handle the output (a model can have multiple views observing it). As mentioned earlier, Backbone is not traditional MVC framework because it does not have a distinct Controller. In Backbone, the Controller responsibility is merged into the View and performed by the template, not the Backbone.View.
Templates - Templates are rendered by Underscore. For better performance templates should be pre-compiled.
<%...%>- execute arbitrary code
<%=...%>- evaluate an expression and render the result inline
<%-...%>- evaluate an expression and render the html escape result inline
If you specify a comparator (either a custom method or by using one of Underscore’s sorting methods), Backbone will automatically sort all Models added to the collection.
Event listeners can added to collections to be triggered when models are added or removed from a collection.
set() - can perform add, remove, and change operations on a collection.
reset() - replaces all collection contents.
remove() - removes a model from the collection but not from the server.
fetch() - sends a GET request to the location in the collection’s url property to retrieve a JSON array of models. After the models are received, set() is automatically executed to update the collection. By default, it merges any new data from the server with any data already on the client.
create() - creates a new collection.
Routers are what Backbone and other frameworks use to simulate page changes. They enable single page applications. Using the router class and only one HTML file, you could create an entire site with an unlimited number of virtual pages.
Routes are set using key-value pairs where the key is the URL route and the value is the function that is called when a user navigates to that route. HTTP requests are routed through a single entry point where they are analyzed by the Front Controller that invokes the method of the corresponding controller.
Each time a user browses a page, the router decides which Views to render and records the visit in the Backbone.history object that allows visitors to use the browser’s Back button to navigate Backbone applications. Note that the history object does not replace the browser’s history. It manages what gets added to the history and when.
Backbone allows you to choose from either the default hash-based (eg. www.mysite.com/foo#bar) routing or the HTML5 pushState approach that results in cleaner URLs but is not supported by older browsers.
Events are a key component of Backbone and any other front-end framework or model and, since they are mixed in with other components, mastering their usage is key to becoming productive with Backbone.
Sync maps Backbone data to the server and thereby handles all persistence. Whenever Backbone tries to read, save or delete models, Backbone.sync is called. Although sync uses jQuery’s $.ajax() to make RESTful requests, it can be overridden globally or by adding a sync function to a Backbone collection or model.
Backbone.sync is called with the following 3 parameters:
- method - read, create, update, delete, patch or delete
- model - the Backbone model object
- options - typically include success or error handling methods
Where Drupal 8 Uses Backbone
The only uses of Backbone I am aware of in Drupal core is its toolbar interaction handling and in-place editing.
Backbone was chosen for inclusion by the Drupal community in 2011 but today it’s one of the older front end libraries in use. Since then, several other front end libraries and frameworks have emerged. While Backbone has proven itself in production and has a vibrant community of developers who have authored a wide array of extensions, libraries and testing tools, I would be more comfortable using an open source library with a company behind it like AngularJS or ReactJS.
Since Backbone is a library and not a framework, it can work with other front end libraries. Unlike some of the front-end frameworks, Backbone doesn’t need to control the whole page. It can be used on a small section of the page so a good use case for Backbone in Drupal might be for data-rich, in-page applications.