一、应用场景
模型层通常是MVC架构的核心。通过监听模型层数据的变化驱动界面的开发,从而解耦视图层,是MVC的精髓。
适用于:
(1)体验型应用。交互比较复杂比如邮箱、购物车、网盘等应用。
(2)CRUD应用。企业信息系统,大多为列表的增删改查。backbone的模型提供数据操作的API(save、fetch、destroy)可以同基于restful思想设计的接口服务通信。
二、构造函数。主要做了以下几件事儿。
(1)、model实例上新增实例属性:cid、attributes、changed等
(2)、将this.defaults,如果 this.defaults未定义则通过原型链查找到this.prototype.defaults对象扩展到临时对象attrs上
(3)、调用set方法将defaults对象的属性扩展到实例属性:attributes、_previousAttributes对象上。示例:
以上语句执行之后,打印出的model实例如下图:
(4)、最后调用你自定义的initialize方法,这也是你自定义的initialize方法无需手动调用的原因,new的过程中initialize方法会执行。如:
new M2012.Mpost.MyMagazine.Model()后框架会调用你自定义的initialize方法,完成初始化工作。
三、核心方法 set
set方法主要做以下几件事:
(1)、新增实例属性_previousAttributes,将当前实例属性attributes克隆到实例属性_previousAttributes中,用传进来的键值对修改实例属性attributes
(2)、触发实例对象上绑定的change事件
(3)、可以传递第三个参数options.silent来控制框架是否触发change事件
set方法的应用场景:
我们知道要实现MVC分层,观察者模式是比较好的选择,backbone的事件机制on、trigger其实是观察者模式的一种实现,而Events模块扩展了Model的原型。所以model实例也具备这种on、trigger事件机制。示例:
var myMagazineModel = new M2012.Mpost.MyMagazine.Model();
var myMagazineView1 = new M2012.Mpost.MyMagazine.View1({model : myMagazineModel });
var myMagazineView2 = new M2012.Mpost.MyMagazine.View2({model : myMagazineModel });
myMagazineView1.model.on('change:contentType', function(){
myMagazineView1 .render();
});
myMagazineView2 .model.on('change:contentType', function(){
myMagazineView2 .render();
});
myMagazineModel .set('change:contentType', 2);
1、如下图,myMagazineModel 的contentType默认值为1,当语句myMagazineModel .set('change:contentType', 2);执行之后,myMagazineView1与myMagazineView2 绑定在模型层的回调函数会执行,渲染各自的界面。
2、参数options.silent
myMagazineModel .set('change:contentType', 2) 修改为 myMagazineModel .set('change:contentType', 2,{silent : true});
语句执行后,myMagazineModel.attributes.contentType的值被改成了2,但是change:contentType事件并没有触发.
3、参数options.unset
通过unset方法的注释可知:
如果传递了unset=true,框架将移除对应的属性(从modelInstance.attributes对象中delete掉),然后判断是否silent是否为true,如果不为true则执行change事件。myMagazineModel .set('change:contentType', 2) 修改为 myMagazineModel .set('change:contentType', 2,{unset : true});语句执行后,contentType从myMagazineModel.attributes对象上移除掉了,但是myMagazineModel._previousAttributes对象上依然有contentType属性,同时change:contentType事件也触发了。
四、通过对set方法剖析,我们可以总结一下实例属性:attributes、_previousAttributes、changed以及局部变量:changes都有哪些作用。
通过以上源码可知:
1、attributes除了扩展用户自定义的defaults属性,调用set方法为不存在的属性赋值也会往attributes对象中添加新属性。
示例:
以上代码自定义的defaults属性中并没有viewType,调用set方法:
var myMagazineModel = new M2012.Mpost.MyMagazine.Model();
myMagazineModel.set({viewType : 1});
console.log(myMagazineModel);
输出结果:
可以看到,
attributes对象中已经有了属性viewType,接下来我们就可以为viewType绑定change事件,监听值的变化:
myMagazineModel.on('change:viewType', function(){});
2、_previousAttributes 维护修改前的属性值。在调用set方法改变attributes中的属性值时,首先克隆一份值保存到_previousAttributes中:
提供以下方法访问_previousAttributes 中的值:
3、changed 维护改变过的属性值。
提供以下方法访问 changed 中的值:
4、局部变量changes比较重要。每一次调用set方法,changes初始化为空数组[],判断属性是否有变化,将变化的属性push到changes中,遍历changes数组触发change事件。
五、get方法。比较简单,返回attributes实例属性对应的键值。
六、与服务端通讯的相关方法:
Backbone.Model.prototype提供了与服务端RESTful接口通讯的相关方法。关于RESTful的介绍,戳这里RESTful
(1)、fetch方法:
注释写的比较清楚:
从服务端获取数据,用数据覆盖model实例对象的attributes属性,如果attributes的当前值与获取数据的对应值不一致,则触发绑定的change事件。
(2)、save方法:
注释写的比较清楚:
从服务端获取数据,用数据覆盖model实例对象的attributes属性,如果attributes的当前值与获取数据的对应值不一致,则触发绑定的change事件。
(3)、destroy方法
注释:
向服务端发送一条删除数据的请求,如果传递了参数‘wait: true’则等待服务端成功响应后再将model实例从其所属的Collection集合中删掉,否则立即删掉。
fetch 、save等方法要求服务端的接口设计符合RESTful规范。ajax请求调用了Backbone.sync模块(其它系列会单独讲解该模块),而sync模块最终调用jquery的ajax方法发送http请求。
通常我们的应用由于某些特殊的需求场景,比如:拦截请求添加统一的头部,报文格式的转换,日志上报等等,我们会封装自己的通讯层,并不会使用jQuery提供的通讯方法。因此,上面那些方法在139邮箱中使用较少。
七、_validate方法。
考虑以下应用场景:
我们在调用set方法时希望对数据进行校验,校验通过则对attributes重新赋值,校验不通过则触发我在业务层绑定的事件。
_validate可满足我们的需求。set方法在给attributes对象赋值之前总是会首先调用_validate方法做验证:
验证不通过则直接返回。我们看一下_validate方法:
看源码我们得出这样的结论:只要我们在业务层实现validate方法,并为model实例绑定invalid方法,调用set方法时传递参数{validate : true},backbone就会执行我们的验证方法validate,验证失败则触发我们的事件invalid 示例:
输出结果:
至此,Backbone.Model的核心方法就讲解完了,还有其它一些工具方法如:escape、has、unset、clear等方法比较简单就不讲了。