single-page javascript appsromania.amazon.com/academy/pdf/day2_1.pdfbackbone.js library overview...

Post on 29-May-2020

7 Views

Category:

Documents

0 Downloads

Preview:

Click to see full reader

TRANSCRIPT

Single-Page JavaScript Apps

with RequireJS and Backbone.js

Mihai Bîrsan

Who is this guy?

Mihai Bîrsan Sr. Web Development Engineer

Email Tools Team

Amazon Development Center Romania

→ We’ve recently rebuilt our project’s UI using Backbone.js and Require.js (among others)

• Single-Page Applications explained

• Example application

• MVC and Backbone.js

• AMD and Require.js

What are Single-Page Applications?

• Recent new way to develop web applications

What are classic web applications?

• Request → Page response

• Page-by-page

• The web was invented as a collection of static documents

What are Single-Page Applications?

• JavaScript client application

• Pulls data with AJAX

• Has an internal state that’s not necessarily represented on the server

Examples in the wild

Classic web applications • Forums • Every web application

before AJAX

Single Page Applications • Gmail • Amazon Search Page

How do we develop TodoMVC

• Think about the architecture of the app

• Separate concerns –data: the actual to-do items

–presentation: displaying data

–behavior: creating and filtering data

How do we develop TodoMVC

Model

Controller

View data

behavior

presentation

MVC and Single Page Applications

• Built around user input → Events

• No single point of control → No Controller

How do we develop TodoMVC

Model

Events

View data

behavior

presentation

Scaffolding: Basic structure

• index.html — obviously, the container

• styles/*.css — the presentation

• javascripts/*.js — the behavior

• javascripts/main.js — app entry point

Backbone.js Library Overview

• Models & Collections

• Views

• Events

• Router

Backbone Model

• A special type of object

• Keeps track of changed attributes

• Fires events when its internal state changes

var TodoModel = Backbone.Model.extend({ // Default attributes for the todo // and ensure that each todo created

// has `title` and `completed` keys. defaults: { title: '', completed: false }, // Toggle the `completed` state of this todo item. toggle: function () { this.save({ completed: !this.get('completed') }); } });

Todo Model

Model usage example

var todo = new TodoModel({ text: "Do the dishes." });

// Later: Update the text

todo.set("text", "Do the dishes NOW!");

todo.save();

// Even later: Mark the task as complete

todo.toggle();

Todos Collection

var TodosCollection = Backbone.Collection.extend({ // Reference to this collection's model. model: Todo, // Filter down the list: all finished todo items. completed: function () { return this.filter(function (todo) { return todo.get('completed'); }); }, // Filter down the list: all incomplete todo items. remaining: function () { return this.without.apply(this, this.completed()); } });

Collection usage example

var todos = new TodosCollection([ { text: "Get milk" }, { text: "Make cake" }, { text: "Eat the cake" } ]);

// Mark the first item as completed todos.at(0).toggle();

// Check number of incomplete items console.log(todos.remaining().length);

Displaying information

• Application View –displays the whole collection

–uses Todo views to display each model

• Todo View –displays a single Todo model

Todo View

var TodoView = Backbone.View.extend({ tagName: 'li', // This is a function that generates HTML template: _.template(todosTemplate), render: function () { this.$el.html(this.template(this.model.toJSON())); this.$el.toggleClass( 'completed', this.model.get('completed') ); this.toggleVisible(); this.$input = this.$('.edit'); return this; },

Tying it up with events

• View events trigger changes in the model – click the check mark → toggle the completeness

– edit the input → update the text

Todo View’s own events

var TodoView = Backbone.View.extend({

events: { 'click .toggle': 'toggleCompleted', 'dblclick label': 'edit', 'click .destroy': 'clear', 'keypress .edit': 'updateOnEnter', 'blur .edit': 'close' },

// Toggle the `"completed"` state of the model. toggleCompleted: function () { this.model.toggle(); },

some lines hidden

Tying it up with events

• Model events trigger updates in the view –when any code makes a Todo invisible → the view hides it

–when any attribute of the model changes → the view re-renders

Todo View’s model events

var TodoView = Backbone.View.extend({

initialize: function () { this.listenTo(this.model, 'change', this.render); this.listenTo(this.model, 'destroy', this.remove); this.listenTo(

this.model, // the object to listen to

'visible', // the event name this.toggleVisible // the function to call

); },

toggleVisible: function () { this.$el.toggleClass('hidden', this.isHidden()); },

};

some lines hidden

some lines hidden

More interesting code

• app.js — the main application view

• router.js — Backbone Router to respond to URL changes and update it

• templates/*.html — partial HTML documents, transformed with _.template()

Interconnected modules

App View

Todo View

Todo Model

Todos Collection

Todo Model

Interconnected modules, actually

App View

Todo View

template todos.html

Todo Model

template stats.html

Todos Collection

Todo Model

jQuery Backbone

Underscore Utilities

Require.js Library Overview

• Define dependencies

• Asynchronously load dependencies

Dependencies in app.js

define([ 'jquery', 'underscore', 'backbone', 'collections/todos', 'views/todos', 'text!templates/stats.html', 'common' ], function ($, _, Backbone, Todos, TodoView, statsTmpl, Common) {

some lines missing

Prettier define call, IMHO

define(function (require) { var $ = require('jquery'), _ = require('underscore'), Backbone = require('backbone'), Todos = require('collections/todos'), TodoView = require('views/todos'), statsTmpl = require('text!templates/stats.html'), Common = require('common');

some lines missing

How definition works

• Each file contains one module

• Modules are defined by calling define

• The callback passed to define returns the actual module object

The definition of Todo Model

define([ 'underscore', 'backbone' ], function (_, Backbone) { 'use strict'; var TodoModel = Backbone.Model.extend({ }); return TodoModel; });

some lines hidden

How dependencies are loaded

• The string passed to define or require is the path of the JavaScript file

• If require has already loaded the file the associated module is returned

• Else the module is being loaded

• The callback is called once all modules have been loaded

The require function

• In the simplified version of define call, it is magically transformed → require("...") is never called!

• Will always return immediately

–the module, if already loaded

–null, if not loaded; also starts loading

• Can be passed a callback

The require function

// In an arbitrary script (not in define) var _ = require('underscore'); // _ is null, because require hasn't loaded Underscore yet

// Much later, after Underscore has been loaded var _ = require('underscore'); // _ is the expected Underscore object

// Altogether, if necessary require(['underscore'], function (_) { // Underscore is loaded when this function is called });

What about saving the data?

• localStorage is used for this example

• after the break we talk about a back-end solution for storing data, working out of the box with Backbone

When not to use this

• Not all problems have to be solved with the MVW pattern

• Choose the pattern that best suits the situation

• One-off scripts and hacks don’t need this

Hack it today!

• http://todomvc.com/

• http://backbonejs.org/

• http://requirejs.org/

fork it on

Thank you! Questions?

top related