Backbone学习之todos实现

最近在读Addy Osmani的Developing Backbone.js Applications,读到了第一个栗子todos,必然要合上书自己再实现一遍。
书上用了一个backbone.localStorage插件,backbone还在初学,不想理会插件,先用window.localStorage直接原始的处理,之后在研究这个插件。

 

Model部分

todo.js

var app = app || {};

app.Todo = Backbone.Model.extend({
    defaults: {
        content: '',
        completed: false
    },

//toggle完成状态 toggle:
function(bool) { if(bool === true) { this.set('completed', true); } else if(bool === false) { this.set('completed', false); } else { this.set('completed', !this.get('completed')); } } });

 

Collection部分

todos.js

var app = app || {};

(function () {
    var TodoList = Backbone.Collection.extend({
        model: app.Todo,
     
//window.localStorage  storage: window.localStorage
|| null, initialize: function() { this.on('all', this.updateStorage, this); }, remaining: function () { return this.filter(function (todo) { return todo.get('completed') === false; }); }, completed: function () { return this.where({completed: true}); },
//页面初始化时加载,用reset方法一次放入所有model,会触发collection的reset事件 readStorage:
function() { if (!this.storage) return; var todo_json = this.storage.getItem('todo'); if (todo_json) this.reset(JSON.parse(todo_json)); },
//任何变动就更新storage的数据
//JSON.stringify,被转换对象如果有toJSON()方法,则转换toJSON()的返回值而不是当前对象了,Model的toJSON()返回它的attriubutes属性,Collection的toJSON(),返回包含所有内部model的attributes对象的数组
updateStorage:
function() { if (!this.storage) return; var todo_json = JSON.stringify(this); this.storage.setItem('todo', todo_json); } }); app.todos = new TodoList(); })();

 

视图部分

item-view.js, 控制ul里每一项li

var app = app || {};

app.TodoView = Backbone.View.extend({
    tagName: 'li',

    template: _.template($('#item-tpl').html()),

//没有用keypress,非字符键不会触发keypress,捕捉不到ESC键。keydown返回键盘的代码,keypress是把keydown返回值翻译为ASCII码 events: {
'dblclick label': 'edit', 'click .toggle': 'toggle', 'blur .edit': 'close', 'keydown .edit': 'updateOnEnter', 'click .clear': 'clear' }, initialize: function() { this.listenTo(this.model, 'change', this.render); this.listenTo(this.model, 'destroy', this.remove); }, render: function() { this.$el.html(this.template(this.model.toJSON())); this.$el.toggleClass('completed', this.model.get('completed')); this.$edit = this.$('.edit'); return this; }, edit: function() { this.$el.addClass('editing'); this.$edit.focus(); this.$edit.select(); }, close: function() { var value = this.$edit.val(); if(value.trim()) { this.model.set('content', value); } else { this.clear(); } this.$el.removeClass('editing'); }, updateOnEnter: function(e) { if(e.which === ENTER_KEY) { this.close(); } else if(e.which === ESC_KEY) { this.$el.removeClass('editing'); this.$edit.val(this.model.get('content')); } }, clear: function() { this.model.destroy(); }, toggle: function() { this.model.toggle(); } });

 

app-view.js

var app = app || {};

app.AppView = Backbone.View.extend({
    el: '#todo-app',

    template: _.template($('#footer-tpl').html()),

    events: {
        'keydown #new-todo': 'createOnEnter',
        'click #toggle-all': 'toggleAll',
        'click .clear-completed': 'clearCompleted'
    },

    initialize: function () {
        this.$list = this.$('#todo-list');
        this.$new = this.$('#new-todo');
        this.allCheckbox = this.$('#toggle-all')[0];
        this.$main = this.$('#todo-main');
        this.$footer = this.$('#todo-footer');
        this.listenTo(app.todos, 'add', this.addOne);
        this.listenTo(app.todos, 'all', this.render);
        this.listenTo(app.todos, 'reset', this.addAll);
        app.todos.readStorage();
    },

    render: function () {
        var remaining = app.todos.remaining().length,
            completed = app.todos.completed().length;

        this.$footer.html(this.template({
            remaining: remaining,
            completed: completed
        }));

        this.$clearCompleted = this.$('.clear-completed');

        this.allCheckbox.checked = !remaining;

        if (app.todos.length) {
            this.$main.show();
            this.$footer.show();
        } else {
            this.$main.hide();
            this.$footer.hide();
        }

        return this;
    },

    newAttributes: function () {
        return {
            content: this.$new.val(),
            completed: false
        }
    },

    addOne: function (todo) {
        var view = new app.TodoView({model: todo});
        this.$list.append(view.render().el);
    },

    addAll: function(todos) {
        todos.each(function(todo) {
            this.addOne(todo);
        }, this);
    },

    createOnEnter: function (e) {
        if (e.which === ENTER_KEY && this.$new.val().trim() != "") {
            app.todos.add(this.newAttributes());
            this.$new.val('');
        }
    },

    clearCompleted: function () {
        app.todos.completed().forEach(function (todo) {
            todo.destroy();
        });
    },

    toggleAll: function () {
        var value = this.allCheckbox.checked;
        app.todos.forEach(function (todo) {
            todo.toggle(value);
        }, this);
    }
});

 

最后,index.js

var ENTER_KEY = 13,
    ESC_KEY = 27,
    app = app || {};

$(function() {
    new app.AppView();
});

 

转载于:https://www.cnblogs.com/coiorz/p/4823646.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值