Backbone as the Next Step After jQuery
Why Backbone?
Backbone is a lightweight library to organize your code in an object-oriented style. If you're used to getting it done with jQuery, you might sometimes find it hard to maintain the code, when it is anything beyond trivial. Backbone to the rescue!
Integration with jQuery
Backbone depends on jQuery to query and manipulate DOM elements in your app. For many developers that means being able to take very familiar steps to make things happen in your app.
Perhaps you're aware of a good practice to save a jQuery object with DOM element references to a variable, especially if you're going to work with the same set of elements more than once:
var $submenu = $('nav .submenu'); /* <- save the `ul` element, so that the browser doesn't have to do the work of finding it again */
$submenu.toggle(); /* <- use the previously found element */
With Backbone you will go one step further, and use a View object to keep a reference to the DOM element:
var submenu = new Backbone.View({ el: 'nav .submenu' });
submenu.$el.toggle();
There are several things to notice here:
- Use
Backbone.Viewprototype to create a new object instanse( How does that work? ) - Pass object with options to the constructor
eloption can be a selector string. Backbone will use jQuery to find the element.- The created
submenuobject has$elproperty, which is a jQuery object, so you can call any jQuery methods on it.
Now, why go all the trouble of creating an object with an $el property, when you could simply create a variable, as in the first example? Because that's when object-oriented programming starts, which will help understand, write and maintain your application so much more.
Backbone.View
You will actually use Backbone.View to create your own types of elements, that will have their own templates, logic and interaction, shared between all items of a particular view prototype.
var UserView = Backbone.View.extend({});
var joe = new UserView();
joe.$el.appendTo( document.body );
Notice:
- We used
extendmethod to create a copy ofBackbone.Viewprototype. - We could, but we didn't have to pass
eloption when we created instance of theUserView - An
$elproperty was created for us by Backbone, and contains adivelement by default. ThedivDOM element exists only in memory. - We can still use all jQuery methods, which is useful to add the newly created element to the page, in our example.
Right now we have an empty <div></div> appended to our page, which we can only see by inspecting the page. How do we display anything within that div?
View: render method
Meet .render method:
var UserView = Backbone.View.extend({
render: function(){
this.$el.html( '<h1>Hello, World, I am a user of this app</h1>');
return this;
}
});
var joe = new UserView();
joe.render().$el.appendTo( document.body );
Notice:
- We created
rendermethod, which is used to keep rendering logic. - The "render" name is just a convention, Backbone doesn't call this method for you.
- You can access
$elproperty within a prototype method withthis.$el - You can use any jQuery methods to manipulate the element
- Remember to
return thisin the last line of therenderto make chaining work, something we've all learned to appreciate with jQuery - Lastly remember to actually call
render, and the template will be rendered within the element.
Backbone.Model
So now we have a template, but how do we pass data there, and have an actual user's name in the template?
Meet Model — where data should be kept and maintained. Model prototype is a blueprint for the data, and model instances are data items that will follow the pattern.
var User = Backbone.Model.extend({
defaults: {
name: '',
age: 0
}
});
var joe = new User({ name: 'Joe', age: 22 });
Notice:
- We created a
Userprototype by extendingBackbone.Model, just as we did withBackbone.View. - We used
defaultsproperty to set default values for properties of the model. - While
defaultsmethod is not required, it will help document which properties a particular model is going to have, and will define default values for the properties, which will help avoid some bugs. - We create an instance of the
Usermodel and pass an object with actual data to the constructor.
Object joe, except for just storing data, includes some useful methods and logic, that will greatly help maintain the data in an application.
Interaction with a model instance.
At the very least, you should use get and set methods to read and change the data in your model.
console.log( joe.get('name') );
joe.set({ age: 23 });
- Use
getmethod to read a property value. - Pass object with the keys and values that should be changed to the
setmethod.
Model and View together
Now that we know what a model looks like, it's time to use it together with a view to render actual data on a page.
Right at this point it is important to remember, that data should never be aware of how it is displayed. We will pass a model object to a view, and the view will own the model object as it's property, will read the data from it, and will be allowed to update the data.
var User = Backbone.Model.extend({});
var UserView = Backbone.View.extend({
render: function(){
this.$el.html('<h1>Hello, I am ' + this.model.get('name') + '</h1>');
return this;
}
});
var joe = new User({ name: 'Joe', age: 22 }); // <-- data is stored here
var joeView = new UserView({ model: joe }); // <-- passing the model to the view
joeView.render().$el.appendTo( document.body ); // <-- render and append to the page
Notice:
- When creating a
UserViewinstance, we passedmodelproperty, and a model instance as it's value. - That makes the model instance available as
modelproperty of the view - Just as we use
this.$elto get to the view's DOM element, we'll usethis.modelto get to its data
Now you might be asking yourself, why did we have to create a model, if we could have just passed a JavaScript object with the same data to the view? Meet Backbone.Events.
Backbone.Events
Backbone.Events prototype is not used directly, but because it is included into every Backbone prototype. It can be used as a publish/subscribe mechanism, a means of communication between Backbone instances.
Simple example:
var joe = new Backbone.Model({ name: 'Joe', age: 22 });
var callback = function(m){
console.log( 'Model changed:', m.toJSON() );
}
joe.on('change', callback); // <- subscribe to any change in the model
joe.set({ age: 23 }); // make a change, and that will fire the callback
Notice:
- You can subscribe to a Backbone event with
onmethod, available in any Backbone instance - "change" is one of built-in Backbone events, which is fired when a model's data changes.
- The model is passed to the callback function as an argument
- Model has
toJSONmethod, which returns a javascript object with properties and values of the model. That's right, it doesn't really returns a JSON string, but a JavaScript object.
Listening to data change from a view
var User = Backbone.Model.extend({});
var UserView = Backbone.View.extend({
initialize: function(){
this.listenTo( this.model, 'change', this.render );
},
render: function(){
this.$el.html('<h1>Hello, I am ' + this.model.get('name') + '</h1>');
return this;
}
});
var joe = new User({ name: 'Joe', age: 22 });
var joeView = new UserView({ model: joe });
joeView.render().$el.appendTo( document.body );
joe.set({ age: 23 }); // make a change, view will call render
Notice:
initializeis a special method which is called when an instance of a Backbone prototype is created (exactly where you see thenewkeyword)- Instead of calling
model.onit is better to useview.listenTo, which will make sure the listener stays in the object that listens, and not in the one that emits events. That makes it easy to remove a view withremovemethod, without having to worry about the listeners. - Whenever "change" event happens in the model instance of that particular view,
rendermethod is called, which takes care of the up-to-date date being displayed.
Backbone.Collection
Backbone.Collection is an array on steroids.
Often it makes little sense to create an instance of a model directly from a model. It would be hard to manually create instances of a User model for every joe, alice, carl and every other user of your application. It's much easier to imagine you would have an array of users.
To easily get models from an array into your application, use Backbone.Collection.
var User = Backbone.Model.extend({});
var Users = Backbone.Collection.extend({
model: User
});
var users = new Users();
Notice how the User prototype was passed to the Users prototype. Now Users collection knows that it is going to contain items of User model.
That means we can just add data objects to the Users collection, and internally Backbone will create instances of User model.
users.add({ name: 'Joe', age: 22 });
Or add an array of objects:
var users_data = [
{ name: 'Alice', age: 21 },
{ name: 'Carl', age: 31 }
];
users.add( users_data);
Note:
- Mind
Usersvsusers.Usersis the prototype of the collection, whileusersis an instance of the collection, which will actually contain data.
Rendering Collection
Backbone.Collection contains all the usual methods to work with an array, and more. Going through a collection is straightforward with each method:
users.each(function( user ){
var view = new UserView({ model: user });
view.render().$el.appendTo( document.body );
});
Notice:
- The callback function passed to
eachmethod will expectedly be called for every item of the collection. - The callback will be called with a model instance as an argument.
- Typically, within the callback function you would create an instance of the respective view, pass current model there, render and append the view to a desired element.
Views and DOM events
It is particularly interesting that it's easy to define DOM event callbacks that will be contained within each view instance.
var UserView = Backbone.View.extend({
render: function(){
this.$el.html('<h1>Hello, I am ' +
this.model.get('name') +
'</h1><span class="close">X</span>');
return this;
},
events: {
'click .close': 'remove'
}
});
Notice:
eventsproperty is special inBackbone.View. Backbone will look into this property when a new instance of the view is created, and will use it to define callbacks for DOM events that will fire within that particular instance.- Every
Backbone.Viewhasremovemethod, which will remove the whole element from the screen. - "remove" method is called when you click ".close" element, and only that one instance of the
UserViewwill be removed from the screen, others will stay untouched. - Read more about how DOM events and callbacks are defined: backbonejs.org/#View-events
Complete example
See the Pen LNjOmO by Yuriy Linnyk (@yuraji) on CodePen
Cheers
I hope this quick overview have shown you how straightforward it is to get started with Backbone, and how it's simplicity keeps Backbone heard among the most popular frameworks, without major changes over past years. Sometimes all you need is a simple tool that gets the job done without too much behind the scenes magic.
If you would like to learn more, or discuss Backbone and the tooling around it, definitely let me know.

Get the latest and best resources about web development
https://www.hotjs.net/