Client-side MVC with Backbone.js (reloaded)
-
Upload
iloveigloo -
Category
Technology
-
view
7.890 -
download
1
description
Transcript of Client-side MVC with Backbone.js (reloaded)
Client-side MVC with Backbone.js
igloolab.com@iloveigloo
michele.berto.li@MicheleBertoli
igloo
Moniga Del Garda
Lago di Garda
jQueryHTML5 UPLOADER
igloolab.com/jquery-html5-uploader
KOALAkoooala.com POMODORO WEBAPP
pomodorowebapp.com
JOBBERONEjobberone.com
SHARP SQUAREigloolab.com/sharpsquare
Agenda
Questions
Why Backbone.js
Architecture
Real World
Tips & Tricks
Extras
14:00 min
05:00 min
06:00 min
04:00 min
NaN
06:00 min
Why Backbone.js
Why Backbone.js
From server-side to client-side
Why Backbone.js
From server-side to client-side
We need efficient tools
Why Backbone.js
jQuery is cool but…
Why Backbone.js
jQuery is cool but…
We have to store object informations intothe DOM
var list = ""; $.each(data, function (index, value) { list += "<li id=\"item-" + value.Id + "\">" + value.Name + "</li>"; }); $("ul").append(list);
Why Backbone.js
jQuery is cool but…
We have to store object informations intothe DOM
var list = ""; $.each(data, function (index, value) { list += "<li id=\"item-" + value.Id + "\">" + value.Name + "</li>"; }); $("ul").append(list);
Why Backbone.js
$.getJSON("/Items", function (data) { var list = ""; $.each(data, function (index, value) { list += "<li id=\"item-" + value.Id + "\">" + value.Name + "</li>"; }); $("ul").append(list);
$("li").click(function () { var $this = $(this); var id = $this.attr("id").replace("item-", ""); $.post("/Items", { id: id }, function () { $this.fadeOut(function () { $this.remove(); }); }); });
});
jQuery is cool but…
jQuery callback hell
Why Backbone.js
jQuery is cool but…
jQuery callback hell
$.getJSON("/Items", function (data) { var list = ""; $.each(data, function (index, value) { list += "<li id=\"item-" + value.Id + "\">" + value.Name + "</li>"; }); $("ul").append(list);
$("li").click(function () { var $this = $(this); var id = $this.attr("id").replace("item-", ""); $.post("/Items", { id: id }, function () { $this.fadeOut(function () { $this.remove(); }); }); });
});
Why Backbone.js
“It's all too easy to create JavaScript applications that end up as tangled piles of jQuery selectors and callbacks.”
Why Backbone.js
So, what do we need?
• Abstraction.
• Decoupling UI from Data.
• No more callbacks.
Why Backbone.js
• A RESTful service based data layer.
• Events (to keep UI and data up-to-date).
• A template engine.
• A solid routing system.
• All the above things wrapped into a lightweight JavaScript framework.
So, what do we need? (More practically)
Why Backbone.js
It exists and it’s called: Backbone.js
Architecture
Architecture
Jeremy Ashkenas
Oct 13th, 2010
Architecture
http://documentcloud.github.com/backbone
https://github.com/documentcloud/backbone
@documentcloud
#documentcloud on IRC
https://groups.google.com/forum/#!forum/backbonejs
Architecture
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.
Architecture
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.
Architecture
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.
Architecture
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.
Architecture
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.
Architecture
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.
Architecture
Dependencies:
• jQuery or Zepto
• Underscore.js
• Json2.js
Architecture
MVC
Model / Collection
Template (View)
View (Controller)
Router
MVC
Model / Collection
Template (View)
View (Controller)
Router
Architecture
MVC
Model / Collection
Template (View)
View (Controller)
Router
Architecture
MVC
Model / Collection
Template (View)
View (Controller)
Router
Architecture
Architecture
MVC
Model / Collection
Template (View)
View (Controller)
Router
Model• Representing data (auto-generated).
• Handling persistence. • Throws events.
• Reusable.
Architecture
• Fetch
• Save (new) • Save
• Destroy
/url
/url /url/id
/url/id
HTTP GET
HTTP POSTHTTP PUT
HTTP DELETE
Model / Collection - View - Template - Router - Utilities
Model
Architecture
var Item = Backbone.Model.extend({ idAttribute: “Id”, urlRoot: “/Items” });
Model / Collection - View - Template - Router - Utilities
Architecture
var item = new Item(); item.set({ Name: “Igloo” }); // trigger change item.save(); // trigger sync
Model / Collection - View - Template - Router - Utilities
Architecture
• extend
• constructor / initialize
• get
• set
• escape
• has
• unset
• clear
• id
• idAttribute
• cid
• attributes
• defaults
• toJSON
• fetch
• save
• destroy
• validate
• isValid
• url
• urlRoot
• parse
• clone
• isNew
• change
• hasChanged
Model / Collection - View - Template - Router - Utilities
Model• changedAttributes
• previous
• previousAttributes
Collection• A list of models.
• Underscore methods.
Architecture
var Items = Backbone.Collection.extend({ model: Item, url: "/Items" });
Model / Collection - View - Template - Router - Utilities
Architecture
var items = new Items(); items.fetch(); // trigger reset
Model / Collection - View - Template - Router - Utilities
Architecture
items.comparator = function(item) { return item.get("Name"); };
Model / Collection - View - Template - Router - Utilities
Architecture
Collection
• extend
• model
• constructor / initialize
• models
• toJSON
• add
• remove
• get
• getByCid
• at
• length
• comparator
• sort
• pluck
• url
• parse
Model / Collection - View - Template - Router - Utilities
• etch
• eset
• create
Architecture
Collection
Model / Collection - View - Template - Router - Utilities
• forEach (each)
• map
• reduce (foldl, inject)
• reduceRight (foldr)
• find (detect)
• filter (select)
• reject
• every (all)
• some (any)
• include
• invoke
• max
• min
• sortBy
• groupBy
• sortedIndex
• shuffle
• toArray
• size
• first
• initial
• rest
• last
• without
• indexOf
• lastIndexOf
• isEmpty
• chain
View• Manipulates the DOM.
• Delegates DOM events.• Has a Model / Collection.
Architecture
View
Model / Collection - View - Template - Router - Utilities
View (Model)
View (Collection)
Architecture
var ListView = Backbone.View.extend({ el: $("ul"), initialize: function () { this.collection.bind("reset", this.render, this); }, render: function () { this.collection.each(this.addItem, this); return this; }, addItem: function (item) { var itemView = new ItemView({ model: item }); this.$el.append(itemView.el); itemView.render(); } });
var ItemView = Backbone.View.extend({ tagName: "li", render: function () { this.$el.text(this.model.get("Name")); return this; } });
Model / Collection - View - Template - Router - Utilities
Architecture
var ListView = Backbone.View.extend({ el: $("ul"), initialize: function () { this.collection.bind("reset", this.render, this); }, render: function () { this.collection.each(this.addItem, this); return this; }, addItem: function (item) { var itemView = new ItemView({ model: item }); this.$el.append(itemView.el); itemView.render(); } });
var ItemView = Backbone.View.extend({ tagName: "li", render: function () { this.$el.text(this.model.get("Name")); return this; } });
Model / Collection - View - Template - Router - Utilities
Architecture
var ListView = Backbone.View.extend({ el: $("ul"), initialize: function () { this.collection.bind("reset", this.render, this); }, render: function () { this.collection.each(this.addItem, this); return this; }, addItem: function (item) { var itemView = new ItemView({ model: item }); this.$el.append(itemView.el); itemView.render(); } });
var ItemView = Backbone.View.extend({ tagName: "li", render: function () { this.$el.text(this.model.get("Name")); return this; } });
Model / Collection - View - Template - Router - Utilities
Architecture
var ListView = Backbone.View.extend({ el: $("ul"), initialize: function () { this.collection.bind("reset", this.render, this); }, render: function () { this.collection.each(this.addItem, this); return this; }, addItem: function (item) { var itemView = new ItemView({ model: item }); this.$el.append(itemView.el); itemView.render(); } });
var ItemView = Backbone.View.extend({ tagName: "li", render: function () { this.$el.text(this.model.get("Name")); return this; } });
Model / Collection - View - Template - Router - Utilities
Architecture
var ListView = Backbone.View.extend({ el: $("ul"), initialize: function () { this.collection.bind("reset", this.render, this); }, render: function () { this.collection.each(this.addItem, this); return this; }, addItem: function (item) { var itemView = new ItemView({ model: item }); this.$el.append(itemView.el); itemView.render(); } });
var ItemView = Backbone.View.extend({ tagName: "li", render: function () { this.$el.text(this.model.get("Name")); return this; } });
Model / Collection - View - Template - Router - Utilities
var ItemView = Backbone.View.extend({ tagName: "li", render: function () { this.$el.text(this.model.get("Name")); return this; } });
Architecture
var ListView = Backbone.View.extend({ el: $("ul"), initialize: function () { this.collection.bind("reset", this.render, this); }, render: function () { this.collection.each(this.addItem, this); return this; }, addItem: function (item) { var itemView = new ItemView({ model: item }); this.$el.append(itemView.el); itemView.render(); } });
Model / Collection - View - Template - Router - Utilities
Architecture
var items = new Items(); var listView = new ListView({ collection: items }); items.fetch();
Model / Collection - View - Template - Router - Utilities
Architecture
View• $ (jQuery or Zepto)
• render
• remove
• make
• delegateEvents
• undelegateEvents
• extend
• constructor / initialize
• el
• $el
• setElement
• attributes
Model / Collection - View - Template - Router - Utilities
Template (Underscore.js)
Compiles JavaScript templates into functions that can be evaluated for rendering.
• Mustache • jQuery-tmpl
ArchitectureModel / Collection - View - Template - Router - Utilities
<script type="text/template" id="item-template"> <li> <%= Name %> </li> </script>
Architecture
var ItemView = Backbone.View.extend({ … template: _.template($("#item-template").html()), ... render: function () { this.$el.html(this.template(this.model.toJSON())); return this; } … });
Model / Collection - View - Template - Router - Utilities
• Maps urls to function.
• Enable history / bookmarking.
Router
ArchitectureModel / Collection - View - Template - Router - Utilities
var AppRouter = Backbone.Router.extend({ routes: { "": "init" }, init: function () { … } });
Architecture
window.AppRouter = Backbone.Router.extend({ routes: { "": "loadInvoices", "/add": "addInvoice", "/show/:id": "showInvoice", "/edit/:id": "editInvoice“ }, loadInvoices: function () { … }, addInvoice: function () { … }, showInvoice: function (id) { … }, editInvoice: function (id) { … } });
Model / Collection - View - Template - Router - Utilities
Router
Architecture
• extend
• routes
• constructor / initialize
• route
• navigate
Model / Collection - View - Template - Router - Utilities
Utilities• History • Sync• Utility
Architecture
Router View
Model /Collection
Template
DataSource
Real World
Real World
• .NET RESTful Web Services / MS SQL • Backbone.js
Polar management• Smart invoicing web application
Technologies
Real World
Polar management
Real World
Real World
Real World
Polar management
window.AppRouter = Backbone.Router.extend({ routes: { … "/modifica/:id": "editInvoice“ }, editInvoice: function (id) { … } });
Polar management
Real World
window.AppRouter = Backbone.Router.extend({ routes: { … "/modifica/:id": "editInvoice“ }, editInvoice: function (id) { … } });
Real World
Koala
• .NET RESTful Web Services / RavenDB • Backbone.js • Highcharts.js
Technologies
• Social media analytics
Real World
Real World
Real World
window.Logs = Backbone.Collection.extend({ model: Log, url: "/Data", comparator: function (log) { return log.get("Date"); }, sum: function (field) { return this.reduce(function (memo, log) { return memo + log.get(field); }, 0); } });
Koala
Real World
window.Logs = Backbone.Collection.extend({ model: Log, url: "/Data", comparator: function (log) { return log.get("Date"); }, sum: function (field) { return this.reduce(function (memo, log) { return memo + log.get(field); }, 0); } });
Koala
Real World
window.Logs = Backbone.Collection.extend({ model: Log, url: "/Data", comparator: function (log) { return log.get("Date"); }, sum: function (field) { return this.reduce(function (memo, log) { return memo + log.get(field); }, 0); } });
Koala
Real World
Cammi
• .NET RESTful Web Services / MS SQL• Backbone.js
Technologies
• Custom newsletter engine
Real World
Cammi
Real World
Cammi
Real World
Cammi
Load User
Load Groups
Load
Companies
Load
Load
Fetch
Fetch
Real World
Real World
Real World
WunderKit
Real World
Groupon
Real World
Basecamp
3
Tips & Tricks
Tips & Tricks
idAttribute: “id”
// CouchDB idAttribute: “_id”
// .NET idAttribute: “Id”
idAttribute
Tips & Tricks
Related Models
Tips & Tricks
var Invoice = Backbone.Model.extend({ idAttribute: “Id” }); var Invoices = Backbone.Collection.extend({ model: Invoice, url: "/Invoices" });
Related Models
Tips & Tricks
Related Models
Tips & Tricks
Related Models
Tips & Tricks
var InvoiceDetail = Backbone.Model.extend({ idAttribute: “Id” }); var InvoiceDetails = Backbone.Collection.extend({ model: InvoiceDetail, url: "/InvoiceDetails“ });
Related Models
Tips & Tricks
var Invoice = Backbone.Model.extend({ idAttribute: "Id", initialize: function () { this.setInvoiceDetails(); }, setInvoiceDetails: function () { this.set({ InvoiceDetails: new InvoiceDetails(this.get("InvoiceDetails")) }); } });
Related Models
Tips & Tricks
Related Models
Tips & Tricks
Related Models
Tips & Tricks
Related Models
var Invoice = Backbone.Model.extend({ idAttribute: "Id", initialize: function () { this.setInvoiceDetails(); this.bind("sync", this.setInvoiceDetails); }, setInvoiceDetails: function () { this.set({ InvoiceDetails: new InvoiceDetails(this.get("InvoiceDetails")) }); } });
Extras
Extras
Plugins
• Backbone-Nested
• Backbone.Memento
• Backbone.Validations
• Backbone.localStorage
• backbone.couchdb.js
• …
https://github.com/documentcloud/backbone/wiki/Extensions%2C-Plugins%2C-Resources
Extras
TDD - Jasmine
describe("Todo", function() {
it("Should have a title", function() {
var todo = new Todo();
expect(todo.get("title")).toBeDefined();
});
});
Extras
Backbone is anti-SEO
http://www.spiffyui.org#!css
http://www.spiffyui.org?_escaped_fragment_=css
http://coding.smashingmagazine.com/2011/09/27/searchable-dynamic-content-with-ajax-crawling/
Extras
• http://sproutcore.com (Apple/iCloud)
• http://knockoutjs.com
• http://emberjs.com
• http://batmanjs.org (Shopify)
Extras
• http://www.igloolab.com/downloads/backbone-cheatsheet.pdf
Cheat Sheet
Backbone.js
-
• Lightweight • Powerful • Code is clean (and maintainable)
+
• Too verbose (for small applications)
3Lago di Garda
Questions ?
Graziewww.igloolab.com
@iloveigloo