首页 > 代码库 > 2014/08/08 – Backbonejs

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=http://www.mamicode.com/‘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=http://www.mamicode.com/‘" + (this.model ? this.model.get(‘name‘) : ‘‘) + "‘ class=‘txtName‘ />" +                "<input type=‘button‘ value=http://www.mamicode.com/‘Add‘ class=‘btnAdd‘>");            //cache element            this.txtName = $(this.el).find("input[class=‘txtName‘]")[0];            return this;        },        refresh: function () {            this.txtName.value = http://www.mamicode.com/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=http://www.mamicode.com/‘" + this.model.get(‘name‘) + "‘ /><label>Age:</label><input class=‘appAge‘ type=‘textbox‘ value=http://www.mamicode.com/‘" + 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