Trabalhando com Single Page Application


VICTOR CAVALCANTE



@vcavalcante
victor@cavalcante.net

http://www.Lambda3.com.br

Eventos próximos



27/07 - online
 
02/08 - 03/08 - Rio de Janeiro

Single page applications


1 única página

Comunicação via AJAX

Server side magrinho

Foco na experiência do usuário

Inteligência de apresentação no JS

The Evolution of the Web


http://www.evolutionoftheweb.com

Frameworks spa


Javascript, qual o problema?





Responsabilidades do servidor web


Não precisa mais gerar HTML

Não precisa mais manter estado

API para acesso a dados

Autenticação

Manifesto da Nova web


Menos server Side, mais client side

Menos arrastar e soltar, mais HTML codificado à mão

Menos poluição no HTML, mais CSS

Menos uso do HTML para design, mais foco na semântica

Mais Javascript, muito mais javascript

Arquitetura da aplicação

REST API
Front End
(Backbone.js)

Back End 
(ASP.NET WEB API)



Arquitetura da Aplicação 

↔ 

Backbone Rest
Sync

 View
Events

 ↑

Banco de Dados

Server Model

Model

Backbone.Mode

HTML + CSS

View

Backbone.View 

Model

Events

Applicação


https://github.com/vcavalcante/BackboneDemoCodificando 

App.Model.todo

App.Models.Todo = Backbone.Model.extend({
    defaults: {
        'status': 'incomplete'
    },
    toggleStatus: function () {

        if (this.get('status') === 'incomplete') {
            this.set('status', 'complete');
        } else {
            this.set('status', 'incomplete');
        }
        this.save();
    }
});

App.Collections.Todo



App.Collections.Todo = Backbone.Collection.extend({
    model: App.Models.Todo,
    url: "/api/todo"
});

App.Views.Todo

App.Views.Todo = Backbone.View.extend({
    initialize: function () {
        this.model.on("change", this.render, this);
    },
    events: { "change input": "toggle" },
    toggle: function () {
        this.model.toggleStatus();
    },
    tagName: "li",
    template: _.template("<%=description%>"),
    render: function () {
        this.$el.html(this.template(this.model.toJSON()));
        return this.$el;
    }
});

 Templates

 template: _.template(
"<label class='<% if(status=='complete')print('done')%>'>" +
"<input type='checkbox' <%if(status=='complete') print('checked')%>/>" +
" <%=description%> </label>")
var minhaTodo = new App.Models.Todo({'Description':'Backbone'});
template(minhaTodo.toJSON());
<label class="">
<input type="checkbox">Backbone</label>
var minhaTodo = new App.Models.Todo({'Description':'Backbone','status':'complete'});
template(minhaTodo.toJSON());
<label class="done">
<input type="checkbox" checked> Backbone</label>

App.Views.Todos (View da Collection)

App.Views.Todos = Backbone.View.extend({  //initialize collection
    tagName: "ul",
    render: function () {
        this.$el.empty();
        this.collection.forEach(this.addOne, this);
        return this.$el;
    },
    addOne: function (todo) {
        var todoView = new App.Views.Todo({ model: todo });
        this.$el.append(todoView.render());
    }
});

App.Views.Todos (View da Collection)

App.Views.Todos = Backbone.View.extend({
    initialize: function () {
        this.listenTo(this.collection, "add", this.addOne, this);
        this.listenTo(this.collection, "reset", this.render, this);
    },
 
    tagName: "ul",
    render: function () {
        this.$el.empty();
        this.collection.forEach(this.addOne, this);
        return this.$el;
    },
    addOne: function (todo) {
        var todoView = new App.Views.Todo({ model: todo });
        this.$el.append(todoView.render());
    }
});

App.Router

 App.Router = Backbone.Router.extend({
    initialize: function () {
        App.Collections.todos = new App.Collections.Todo({
            model: App.Models.Todo
        });
        App.Views.todos = new App.Views.Todos({
            el: $("#app ul"),
            collection: App.Collections.todos
        });
        App.Views.addTodo = new App.Views.AddTodo({
            el: "#app form", collection: App.Collections.todos
        });
        App.Views.addTodo.render();
        App.Collections.todos.fetch();
    }
});

Rotas

routes: {
    "all": "all",
    "done": "done",
    "todo": "todo"
}, 
all: function () { 
   $(".brand").html("All"); 
},
done: function () { 
   $(".brand").html("done"); 
},
todo: function () { 
   $(".brand").html("todo"); 
}

Iniciando o Router


Backbone.history.start();
App.router = new App.Router(); 


Made with Slides.com