Anatomy of a SPA:
Client-side MVC
SPA: Single Page Application
MVC: Model-View-Controller
MVC: Model-View-Controller

A metaphor to better understand it.
The MVC pattern is like cookies. Sort of.
The cookie pattern!
Models are the heart of any JavaScript application, containing the interactive data as well as a large part of the logic surrounding it.
// You extend Backbone.Model with your domain-specific methods,
// and Model provides a basic set of functionality for managing
// changes.
var Cookie = Backbone.Model.extend({
defaults: {
'flavour': 'N/A',
'hasChips': false
},
getFlavour: function() {
return this.get('flavour');
}
});
// Simple... huh?
// Extends from Cookie and sets some properties.
var ChocolateCookie = Cookie.extend({
// If you define an initialize() function, it will be
// invoked when the model is created.
initialize: function() {
this.set({
'flavour': 'chocolate'
});
},
// Overriding the set method.
set: function (attributes, options) {
// Do something interesting
// Invoking the parent object's implementation of the
// overriden method.
Cookie.prototype.create.call(this, attributes, options);
}
});
// Default parameters.
var myCookie = new ChocolateCookie({
'hasChips': false
});
myCookie.get('flavour');
// -> 'chocolate'
// This cookie has chips.
myCookie.set({
'hasChips': true
});
// Triggers a 'destroy' event and performs the DELETE action on the
// storage backend.
myCookie.destroy();
// Check all the available methods on the doc (A.K.A. RTFM)
Backbone views are almost more convention than they are code — they don't determine anything about your HTML or CSS for you, and can be used with any JavaScript templating library.
var CookieView = Backbone.View.extend({
tagName: "div",
className: "cookie",
template: _.template($('#cookietemplate').html()),
events: {
"click .cookie": "pickCookie"
},
initialize: function() {
this.model.bind('change', this.render, this);
},
render: function() {
$(this.el).html(this.template(this.model.toJSON()));
return this;
}
});
var myCookie = new ChocolateCookie,
var view = CookieInAJarView({
'model': myCookie
});
// Render a cookie in a jar.
view.render();
var view = CookieOnAPlateView({
'model': myCookie
});
// Now render a cookie on a plate.
// Exactly the same, only changes the View object.
view.render();
// For Backbone's purposes, either jQuery or Zepto owns the // `$` variable. var $ = this.jQuery || this.Zepto;
Collections are ordered sets of models. You can bind events to be notified when any model in the collection has been modified and fetch the collection from the server.
var ChocolateCookieList = Backbone.Collection.extend({
model: ChocolateCookie,
localStorage: new Store('cookies'),
initialize: function() {
// Constructor
}
});
var cookies = new ChocolateCookieList([cookie1, cookie2, cookie3]);
// Get the cookies stored in the backend.
cookies.fetch();
// Get the first inserted cookie.
var first = cookies.at(0);
newCookie = new Cookie({
'flavour': 'pajarito'
});
// Triggers an 'add' event and persists the object.
cookies.add(newCookie);
Backbone.sync is the function that Backbone calls every time it attempts to read or save a model to the server.
By default, it uses (jQuery/Zepto).ajax to make a RESTful JSON request. You can override it in order to use a different persistence strategy.
How to use it?
<script type="text/javascript" src="js/backbone.js"></script> <script type="text/javascript" src="js/backbone-localstorage.js"> </script>
var ChocolateCookieList = Backbone.Collection.extend({
...
localStorage: new Store('cookies'),
...
});
+-----------+ +---------+ +--------+
| | Save() | | Uses | |
| Storage | <-------- | Model | <------ | View |
| | | | | |
+-----------+ +---------+ +--------+
^ ^
| Has many |
| |
+--------------+ |
| | |
| Collection | |
| | |
+--------------+ |
^ |
| |
| |
+--------------------------------------------------+
| Your application |
+--------------------------------------------------+