backbone.js — introduction to client-side javascript mvc

Post on 17-May-2015

5.187 Views

Category:

Technology

0 Downloads

Preview:

Click to see full reader

DESCRIPTION

Using Backbone.js to move state to the client-side and the benefits of using a JavaScript MVC framework. Delivered at SuperMondays, Newcastle upon Tyne, on 26th September 2011.

TRANSCRIPT

Philip Poots

@pootsbook

Ruby Developer

Audacio.us

3

18

3

JavaScript

Structure

State

Speed

Structure Framework

State Application

Speed Javascript

Structure Framework

State Application

Speed Javascript

$.getJSON("http://example.com/?feed=json&jsonp=?", function(data){ $('#content').html("<a href=\"" + data[0].permalink + "\">" + data[0].title + "</a>"); $('#Date').html(data[0].date); $('#Excerpt').html(data[0].excerpt); $('#Excerpt').after("<a href=\"" + data[0].permalink + "\" class=\"more\">read on &raquo;</a>"); });

MVC Model View Controller

Pattern —1979

Architecture

—Separate domain logic & UI

Server-Side MVC

—Ruby on Rails

S T R U C T U R E

MVC on Server S T R U C T U R E

MVC on Client S T R U C T U R E

Backbone Model

window.Todo = Backbone.Model.extend({ defaults: { done: false }, toggle: function() { this.save( {done: !this.get("done")}

); } });

S T R U C T U R E

Backbone Model

window.Todo = Backbone.Model.extend({ defaults: { done: false }, toggle: function() { this.save( {done: !this.get("done")}

); } });

S T R U C T U R E

Backbone Model

window.Todo = Backbone.Model.extend({ defaults: { done: false }, toggle: function() { this.save( {done: !this.get("done")}

); } });

S T R U C T U R E

Backbone Collection

window.TodoList = Backbone.Collection.extend({ model: Todo, localStorage: new Store("todos"), done: function() { return this.filter(function(todo) { return todo.get('done'); }); }, remaining: function() { return this.without.apply( this, this.done()); } });

S T R U C T U R E

Backbone Collection

window.TodoList = Backbone.Collection.extend({ model: Todo, localStorage: new Store("todos"), done: function() { return this.filter(function(todo) { return todo.get('done'); }); }, remaining: function() { return this.without.apply( this, this.done()); } });

S T R U C T U R E

Backbone Collection

window.TodoList = Backbone.Collection.extend({ model: Todo, localStorage: new Store("todos"), done: function() { return this.filter(function(todo) { return todo.get('done'); }); }, remaining: function() { return this.without.apply( this, this.done()); } });

S T R U C T U R E

Backbone Collection

window.TodoList = Backbone.Collection.extend({ model: Todo, localStorage: new Store("todos"), done: function() { return this.filter(function(todo) { return todo.get('done'); }); }, remaining: function() { return this.without.apply( this, this.done()); } });

S T R U C T U R E

Backbone Collection

window.TodoList = Backbone.Collection.extend({ model: Todo, localStorage: new Store("todos"), done: function() { return this.filter(function(todo) { return todo.get('done'); }); }, remaining: function() { return this.without.apply( this, this.done()); } });

S T R U C T U R E

Backbone Collection

window.TodoList = Backbone.Collection.extend({ model: Todo, localStorage: new Store("todos"), done: function() { return this.filter(function(todo) { return todo.get('done'); }); }, remaining: function() { return this.without.apply( this, this.done()); } });

S T R U C T U R E

Backbone View

window.TodoView = Backbone.View.extend({ tagName: "li", template: $("#item-template").template(), events: { "change .check" : "toggleDone", "dblclick .todo-content" : "edit", "click .todo-destroy" : "destroy", "keypress .todo-input" : "updateOnEnter", "blur .todo-input" : "close" },

S T R U C T U R E

Backbone View

window.TodoView = Backbone.View.extend({ tagName: "li", template: $("#item-template").template(), events: { "change .check" : "toggleDone", "dblclick .todo-content" : "edit", "click .todo-destroy" : "destroy", "keypress .todo-input" : "updateOnEnter", "blur .todo-input" : "close" },

S T R U C T U R E

Backbone View

window.TodoView = Backbone.View.extend({ tagName: "li", template: $("#item-template").template(), events: { "change .check" : "toggleDone", "dblclick .todo-content" : "edit", "click .todo-destroy" : "destroy", "keypress .todo-input" : "updateOnEnter", "blur .todo-input" : "close" },

S T R U C T U R E

JS Template

window.TodoView = Backbone.View.extend({ tagName: "li", template: $("#item-template").template(), events: { "change .check" : "toggleDone", "dblclick .todo-content" : "edit", "click .todo-destroy" : "destroy", "keypress .todo-input" : "updateOnEnter", "blur .todo-input" : "close" },

S T R U C T U R E

Backbone View

window.TodoView = Backbone.View.extend({ tagName: "li", template: $("#item-template").template(), events: { "change .check" : "toggleDone", "dblclick .todo-content" : "edit", "click .todo-destroy" : "destroy", "keypress .todo-input" : "updateOnEnter", "blur .todo-input" : "close" },

S T R U C T U R E

Backbone View

initialize: function() { _.bindAll(this, 'render', 'close', 'remove', 'edit'); this.model.bind('change', this.render); this.model.bind('destroy', this.remove); }, render: function() { var element = jQuery.tmpl(this.template, this.model.toJSON()); $(this.el).html(element); this.input = this.$(".todo-input"); return this; },

S T R U C T U R E

Backbone View

initialize: function() { _.bindAll(this, 'render', 'close', 'remove', 'edit'); this.model.bind('change', this.render); this.model.bind('destroy', this.remove); }, render: function() { var element = jQuery.tmpl(this.template, this.model.toJSON()); $(this.el).html(element); this.input = this.$(".todo-input"); return this; },

S T R U C T U R E

Backbone View

toggleDone: function() { this.model.toggle(); },

S T R U C T U R E

Backbone Router

var Workspace = Backbone.Router.extend({ routes: { "help": "help" // #help }, help: function() { ... } });

S T R U C T U R E

Backbone Router

var Workspace = Backbone.Router.extend({ routes: { "help": "help" // #help }, help: function() { ... } });

S T R U C T U R E

Backbone Router

var Workspace = Backbone.Router.extend({ routes: { "help": "help" // #help }, help: function() { ... } });

S T R U C T U R E

Clean Code S T R U C T U R E

Structure Framework

State Application

Speed Javascript

HTTP/1.1 “It is a…stateless protocol” —RFC 2616 (June 1999)

S TAT E

HTTP/1.1 “It is a…stateless protocol” —RFC 2616 (June 1999)

cookies

sessions

form variables

URI parameters

S TAT E

Server Owns State

Server

S TAT E

Client

Request GET / HTTP/1.1 S TAT E

Server Client

Response HTTP/1.1 200 OK S TAT E

Server Client

AJAX asynchronicity S TAT E

Server Client

Infrastructure S TAT E

Client

Server

Infrastructure S TAT E

Client

Web Server

Infrastructure S TAT E

Client

Web Server

RESTful Application

Infrastructure S TAT E

Client

Web Server

RESTful Application

Database

Infrastructure S TAT E

Client

Web Server

RESTful API / App.

Database

JavaScript MVC App.

Infrastructure S TAT E

Client

Local Storage

JavaScript MVC App.

Bonus!

Structure Framework

State Application

Speed Javascript

JavaScript is Fast Google v8 JS engine —focus on optimizing speed

It runs in the browser

—cuts out server requests —spares server resources —instantaneous UI

S P E E D

Data Transport JSON data only —no markup

S P E E D

Data Transport JSON data only —no markup

S P E E D

{ "id": 1, "first_name": "Philip", "last_name": "Poots", "twitter": "@pootsbook"}

"<div id=\"user_1\">\n<dl>\n<dt>Name</dt>\n<dd>Philip Poots</dd>\n<dt>Twitter handle:</dt>\n<dd>@pootsbook</dd>\n</dl>\n</div>"

vs.

Structure Framework

State Application

Speed Javascript

http://documentcloud.github.com/backbone/

JavaScript Web Apps

@maccman

top related