Backbone学习记录(1)
去年买的《基于MVC的javascript Web富应用开发》,拖到现在还没看完,作者介绍了三个MVC框架,Spine ,backbone和javascriptMVC。1和2在国内的流行度,不高,我就只打算学backbone了。
backbone依赖于underscore.js,所以在引入的时候需要先引underscore -_-#
=> Uncaught TypeError: Cannot call method 'each' of undefined
Backbone的模块
1)Events 事件驱动方法
2)Model 数据模型
3)Collection 模型集合器
4)Router 路由(hash)
5) History 开启历史管理
6) Sync 同步服务器方式
7) View 视图(事件行为与渲染页面)
Events模块可以混合到任何模块中。使对象可以绑定和触发自定义事件。
_.extend(Model.prototype, Events, {});
_.extend(Collection.prototype, Events, {});
_.extend(View.prototype, Events, {});
_.extend(Router.prototype, Events, {});
Model与Collection的关系:Collection是Model的集合,对单独的模型集合在一起然后进行整体操作。
backbone的控制器并没有单独分离出来,它与渲染视图一起混杂在View中。
Backbone对象
console.log(Backbone); /*{ $: function ( selector, context ) {}, Collection: function (models, options) {}, Events: Object, History: function () {}, Model: function (attributes, options) {}, Router: function (options) {}, VERSION: "1.1.2", View: function (options) {}, ajax: function () {}, bind: function (name, callback, context) {}, emulateHTTP: false, emulateJSON: false, history: Backbone.History, listenTo: function (obj, name, callback) {}, listenToOnce: function (obj, name, callback) {}, noConflict: function () {}, off: function (name, callback, context) {}, on: function (name, callback, context) {}, once: function (name, callback, context) {}, stopListening: function (obj, name, callback) {}, sync: function (method, model, options) {}, trigger: function (name) {}, unbind: function (name, callback, context) {}, __proto__: Object }*/
Model
看一下Backbone的Model构造器
var Model = Backbone.Model = function(attributes, options) { var attrs = attributes || {}; options || (options = {}); this.cid = _.uniqueId('c'); this.attributes = {}; if (options.collection) this.collection = options.collection; if (options.parse) attrs = this.parse(attrs, options) || {}; attrs = _.defaults({}, attrs, _.result(this, 'defaults')); this.set(attrs, options); this.changed = {}; this.initialize.apply(this, arguments); };
options用第2种写法的原因是其性能更好,如果options存在,就可避免一次赋值的操作
options=options||{};//1 options|(options={});//2
cid属性不知道是干嘛的,为什么要把attributes属性留出来?以及中间那一大堆都在干嘛,最后是调用了initialize方法做初始化工作?
创建一个Model:(好吧,写错了,User和User1都应该用小写开头- -)
var User=new Backbone.Model();
var User1=new Backbone.Model({'name':'susan'});
Model.extend()方法
keys(Backbone.Model) //["extend"]
Model有一个静态方法extend:没看过underscore,源码以后再看 ~~~~(>_<)~~~~
总之,第一个参数对象的属性都被传到了extend生产的构造器的原型上,第二个参数对象的属性都成了extend生成的构造器的静态属性
var extend = function(protoProps, staticProps) { var parent = this; var child; // The constructor function for the new subclass is either defined by you // (the "constructor" property in your `extend` definition), or defaulted // by us to simply call the parent's constructor. if (protoProps && _.has(protoProps, 'constructor')) { child = protoProps.constructor; } else { child = function(){ return parent.apply(this, arguments); }; } // Add static properties to the constructor function, if supplied. _.extend(child, parent, staticProps); // Set the prototype chain to inherit from `parent`, without calling // `parent`'s constructor function. var Surrogate = function(){ this.constructor = child; }; Surrogate.prototype = parent.prototype; child.prototype = new Surrogate; // Add prototype properties (instance properties) to the subclass, // if supplied. if (protoProps) _.extend(child.prototype, protoProps); // Set a convenience property in case the parent's prototype is needed // later. child.__super__ = parent.prototype; return child; };
var User1=Backbone.Model.extend({}); var User2=Backbone.Model.extend({'initalize':function(){console.log('init ing')}}); var user1=new User1(); var user2=new User2();
cid似乎是实例的标志。对比user1和user2,可知,Backbone.Model.extend构造器传入的第一个参数(对象)属性添加到了原型链上。
Backbone.Model.extend生成的User2构造器,比如这里,在实例化User2的时候传入{'name':'susan'},这些键值对最后被保存在了实例的attributes属性中。
var User4=Backbone.Model.extend({'initalize':function(){console.log('init ing')}},{'checkFn':function(){console.log("check fn ing")}}); keys(User4); //["extend", "checkFn", "__super__"]
这里可以看到,checkFn确实是作为了User4的静态属性。
set 和 get方法
var User1=Backbone.Model.extend({}); var user1=new User1({'name':'susan'}); user1.get('name'); //"susan"
从这里可以看到 new User1()的时候传入一个对象参数,等同于user1.set()方法 ?
set的两种用法 : set(name,value) 与 set({name:value})
user1.set('name','lily'); user1.get('name'); //lily user1.set({'name':'lucy','age':'25'}); user1.get('name');//lucy user1.get('age');//25