• 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();
    });
  • 相关阅读:
    沧海桑田,看风险评估在这十五年间的变化与演进
    安全建设从扁鹊三兄弟,到程咬金的三板斧
    基于主动防御能力,建设安全运营体系的一点思考
    如果身处企业高管的位子,你会关心哪些安全问题?
    springsecurity授权
    oracle java api
    oracle知识点
    fastdfs客户端上传和下载文件
    fastdfs知识点
    rabbitmq项目案例
  • 原文地址:https://www.cnblogs.com/coiorz/p/4823646.html
Copyright © 2020-2023  润新知