2014/08/08 – Backbonejs

[来自: Backbone.js 开发秘笈 第5章]

Event API:

(function ($) {
    //define -------------------------
    var obj = {};
    var obj2 = {
        commonEvent: function () {
            window.document.title = new Date().toString();
        }
    };
    //扩展对象包含事件
    _.extend(obj, Backbone.Events);
    _.extend(obj2, Backbone.Events);
    //绑定事件  [ once() 方法绑定的行为只触发一次]
    /* Backbone.Events 会把回调函数保持在一个名为 _events 的关联数组中,随后在调用 trigger() 方法时,它会迭代地执行事件上所有的回调函数。 */
    obj.on(‘test‘, function (args) {
        window.document.title = args;
    });

    $(function () {
        //apply ------------------------------------------------
        //触发事件
        obj.trigger(‘test‘, "Test Title");
        //取消回调函数
        obj.off(‘test‘);
        //obj.off(‘test‘,/* 参数为要取消的指定回调函数 */);
        //obj.off(null,/* 参数为所以事件中要取消的指定回调函数 */);
        //obj.off();取消所有

        //侦听其他对象上的事件
        obj2.listenTo(obj, ‘click‘, obj2.commonEvent);
        obj.trigger(‘click‘);
        //取消侦听
        obj2.stopListening(obj);
        //obj2.stopListening();//取消所有
    });
})(jQuery);

1. 处理 Backbone 对象事件

(function ($) {
    //define -----------------------------
    var model = new Backbone.Model({
        firstName: ‘John‘,
        lastName: ‘Doe‘,
        age: 20
    });
    model.on(‘change‘, function (model) {
        if (model.hasChanged(‘age‘)) {//是否更改了 age 属性
            var oldAge = model.previous(‘age‘);//获取更改前 age 属性
            var oldAttrs = model.previousAttributes();//获取所以变化前的属性
            var upAttrs = model.changedAttributes();//获取所有变化的属性
        }

    });
    /* 内置事件:    http://backbonejs.org/#Events-catalog
       模型事件 -
        change(model, options)
        change:[attribute](model, value, options)
        destroy(model, collection, options)
        invalid(model, error, options)
        error(model, xhr, options)
        sync(model, resp, options)
       集合事件 -
        add(model, collection, options)
        remove(model, collection, options)
        reset(collection, options)
        sort(collection, options)
        sync(collection, resp, options)
       路由事件 -   //注:当执行存储操作时,会触发 route 事件
        route:[name](params)    //name 路由名
        route(router, route, params)    //Backbone 的 history 对象或者路由器会触发事件
       
       all 所以事件
    */

    $(function () {
        //apply ---------------------------------
        model.set(‘age‘, 22);
        model.set({
            firstName: ‘Yo‘,
            lastName: ‘Yo‘
        }, {
            silent: true//不触发 change 事件
        });
    });
})(jQuery);
View Code

2. 模型绑定到视图(视图响应模型的改变)

(function ($) {
    //define -----------------------------------------
    var UserView = Backbone.View.extend({
        el: ‘body‘,
        render: function () {
            $(this.el).html("<p>" + this.model.get(‘name‘) + "</p>");
            $(‘body‘).append("<input type=‘button‘ value=‘Modify‘ onclick=‘updateUserName();‘>");
        },
        initialize: function () {
            //侦听模型变化
            this.listenTo(this.model, ‘change‘, this.render, this);
        }
    });

    $(function () {
        //apply ----------------------------
        var userModel = new Backbone.Model({
            id: 1,
            name: ‘yoyo‘
        });
        var userView = new UserView({
            model: userModel
        });
        window.updateUserName = function () {
            userModel.set(‘name‘, new Date().toString());
        };
        userView.render();
    });
})(jQuery);
View Code

3. 集合绑定到视图

(function ($) {
    //define ------------------------------
    var UserModel = Backbone.Model.extend();
    var UserCollection = Backbone.Collection.extend({ model: UserModel });
    var UserListItemView = Backbone.View.extend({
        tagName: ‘li‘,
        events: {
            ‘click a‘: ‘clickCurrent‘
        },
        initialize: function () {
            //侦听 Model 的变化
            this.listenTo(this.model, ‘destroy‘, function () {
                this.remove();//删除视图
            }, this);
            this.listenTo(this.model, ‘change‘, function () {
                this.render();//刷新视图
            }, this);
        },
        render: function () {
            $(this.el).html("<a href=‘javascript:;‘>" + this.model.get(‘name‘) + "</a>");
            return this;
        },
        clickCurrent: function () {
            //触发 Model 选中事件
            this.model.trigger(‘select‘, this.model);
        }
    });
    var UserListView = Backbone.View.extend({
        tagName: ‘ul‘,
        initialize: function () {
            //侦听 Collection 添加 Model 事件
            this.listenTo(this.collection, ‘add‘, function (model) {
                //视图添加新 Model
                $(this.el).append(new UserListItemView({ model: model }).render().el);
            }, this);
        },
        render: function () {
            $(this.el).html(_.map(this.collection.models, function (model) {
                return new UserListItemView({ model: model }).render().el;
            }));
            return this;
        }
    });
    var UserFormView = Backbone.View.extend({
        tagName: ‘div‘,
        render: function () {
            $(this.el).html("<label>name:</label><input type=‘textbox‘ value=‘" + (this.model ? this.model.get(‘name‘) : ‘‘) + "‘ class=‘txtName‘ />" +
                "<input type=‘button‘ value=‘Add‘ class=‘btnAdd‘><input type=‘button‘ value=‘Update‘ class=‘btnUpdate‘><input type=‘button‘ value=‘Remove‘ class=‘btnRemove‘>");

            //cache element
            this.txtName = $(this.el).find("input[class=‘txtName‘]")[0];

            return this;
        },
        refresh: function () {

            this.txtName.value = this.model ? this.model.get(‘name‘) : "";
        },
        events: {
            "click input[class=‘btnAdd‘]": "add",
            "click input[class=‘btnUpdate‘]": "update",
            "click input[class=‘btnRemove‘]": "remove"
        },
        add: function () {
            if (this.txtName.value.length !== 0) {
                this.model = new UserModel({
                    name: this.txtName.value
                });
                this.collection.add(this.model);
            }
        },
        update: function () {
            if (this.model) {
                this.model.set(‘name‘, this.txtName.value);
            }
        },
        remove: function () {
            if (this.model) {
                this.model.destroy();
                this.model = null;
                this.refresh();
            }
        }
    });
    var ShowView = Backbone.View.extend({
        el: ‘body‘,
        render: function () {
            $(this.el).html([
                new UserListView({ collection: this.collection }).render().el,
                $("<p>---------------</p>")[0],
                (this.currentFormView = new UserFormView({ model: null, collection: this.collection })).render().el
            ]);
            return this;
        },
        initialize: function () {
            //添加侦听 Model 选中事件
            _.each(this.collection.models, function (model) {
                this.listenTo(model, ‘select‘, this.selectModel, this);
            }, this);
            this.listenTo(this.collection, ‘add‘, function (model) {
                this.listenTo(model, ‘select‘, this.selectModel, this);
            }, this);
        },
        selectModel: function (model) {
            this.currentFormView.model = model;
            this.currentFormView.refresh();
        }
    });

    $(function () {
        //instance --------------------------
        var users = new UserCollection([
            { name: ‘123‘ },
            { name: ‘456‘ },
            { name: ‘789‘ },
            { name: ‘012‘ }
        ]);
        var mainView = new ShowView({ collection: users });

        //apply ---------------------------------
        mainView.render();
    });

})(jQuery);
View Code

4. 双向绑定

(function ($) {
    //依赖 backbone.stickit.js
    //https://github.com/nytimes/backbone.stickit

    //define -----------------------------------
    var TitleView = Backbone.View.extend({
        tagName: ‘p‘,
        /* 设置绑定关系 */
        bindings: {
            "span[class=‘appName‘]": ‘name‘,//简写
            "span[class=‘appAge‘]": {
                observe: ‘age‘,
                onGet: function (value, options) {//重写 getter 方法
                    return "Welcome " + value;
                }
            }
        },
        render: function () {
            $(this.el).html("<span class=‘appName‘>" + this.model.get(‘name‘) + "</span><span class=‘appAge‘>" + this.model.get(‘age‘) + "</span>");

            //call binding method
            this.stickit();

            return this;
        }
    });
    var EditView = Backbone.View.extend({
        tagName: ‘div‘,
        bindings: {
            "input[class=‘appName‘]": {
                observe: ‘name‘,
                onSet: function (value, options) {//重写 setter 方法
                    return "Mr." + value;
                },
                /* 重写更新方法
                    update($el,value,model,options)
                    afhterUpdate($el,value,options)
                    updateMethod:‘html‘ (默认 text() 方法)
                */
                events: [‘blur‘]//修改事件的侦听
            },
            "input[class=‘appAge‘]": ‘age‘
        },
        render: function () {
            $(this.el).html("<label>Name:</label><input class=‘appName‘ type=‘textbox‘ value=‘" + this.model.get(‘name‘) + "‘ /><label>Age:</label><input class=‘appAge‘ type=‘textbox‘ value=‘" + this.model.get(‘age‘) + "‘ />");

            //call binding method
            this.stickit();

            return this;
        }
    });

    var MainView = Backbone.View.extend({
        el: ‘body‘,
        render: function () {
            $(this.el).html([new TitleView({ model: this.model }).render().el, new EditView({ model: this.model }).render().el]);
            return this;
        }
    });

    $(function () {
        //instance ----------------
        var modelInstance = new Backbone.Model({ name: ‘YoYo‘, age: 22 });
        var mainView = new MainView({ model: modelInstance });

        //apply --------------------
        mainView.render();
    });
})(jQuery);
View Code

2014/08/08 – Backbonejs,古老的榕树,5-wow.com

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。