前端MVC框架Backbone 1.1.0源码分析(二) - 模型
模型是什么?
Models are the heart of any JavaScript application, containing the interactive data as well as a large part of the logic surrounding it: conversions, validations, computed properties, and access control. You extend Backbone.Model with your domain-specific methods, and Model provides a basic set of functionality for managing changes.
模型 是所有 Javascript 应用程序的核心,包括交互数据及相关的大量逻辑: 转换、验证、计算属性和访问控制。
你可以用特定的方法扩展 Backbone.Model , 模型 也提供了一组基本的管理变化的功能,这个东西就像是后端开发中的数据库映射那个model一样,也是数据对象的模型,并且应该是和后端的model有相同的属性(仅是需要通过前端来操作的属性)。
简而言之,就是围绕着数据处理,如创建、校验、销毁和保存到服务端等等...
如何设计模型
之前说了,模型可以围绕数据处理类似curd的操作,所以backbone就为我们提供了这样的一个基础模板,Backbone中的模型类是Backbone.Model,它包含了数据存储,数据验证,以及数据发生变动时触发相关动作,我们只要继承就能使用这些特性了
用别人的框架,就需要了解别人的规则,这种学习成本是跑不掉的 - -
官方的demo
下面是一个示例,它演示了定义一个模型使用一个自定义的方法,设置一个属性,触发一个事件的特定属性的变化
var Sidebar = Backbone.Model.extend({
promptColor: function() {
var cssColor = prompt("Please enter a CSS color:");
this.set({color: cssColor});
}
});
window.sidebar = new Sidebar;
sidebar.on('change:color', function(model, color) {
console.log('修改颜色',color)
});
sidebar.set({color: 'white'});
sidebar.promptColor();
当models中值被改变时自动触发一个"change"事件、所有用于展示models数据的views都会侦听到这个事件,然后进行重新渲染。
Backbone.Model 是Backbone提供模板类,通过继承extend构造自己Sidebar模型类
所以具有了on ,set 等等这种基础的属性与方法
Backbone.Model
模型构造器
那么我看看backbone模型类模板能为我们提供什么基础功能
- 既然是模型首先就是围绕数据操作,上帝set,上帝get不能少,这样也是为了体现出对象封装性
- 与此同时数据的清理与改变也是不能少的
- 监听对象中属性变化
- 为对象添加验证规则,以及错误提示
- 对象的获取和保存,需要服务器端支持才能测试
- 等等一些围绕的数据的处理了
继承extend
就是把模板类的方法继承给子类,所以我们子类都具有相同的特性了
Backbone.Model.extend
Backbone.Collection.extend
Backbone.Router.extend
Backbone.View.extend
扩充的静态方法
Model.extend = Collection.extend = Router.extend = View.extend = History.extend = extend;
关于这个继承很好理解,js的继承常用的就是这个了
代码简单分析下
创建子类的载体,换句话就是我们构造出来的那个新的类的一个新的构造器
if (protoProps && _.has(protoProps, 'constructor')) {
child = protoProps.constructor;
} else {
child = function () {
return parent.apply(this, arguments);
};
}
如果用户自定义了constructor函数,就用这个,否则就内部自行构建
之后就是复制静态属性到新的child
然后把父类的原型链的引用给指向child
这个请参考http://www.cnblogs.com/aaronjs/archive/2012/08/26/2657103.html

扩展了属性,在constructor中扩展了__super__ 指向父类,继承了模板的原型链上的方法
上帝get/上帝set
可以想像下模型实例用来存储数据表中的一行数据(row)
Backbone利用model的attributes与数据库的字段一一对应
使用set和get方法来设置或获取模型的属性。
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);
};
不能把属性直接写到 Backbone.Model.extend的扩展中,原因也很简单,一个是封装性,最重要的原型上是共享的,如果是引用类型就糟糕了
所以属性在模型实例上有一个专门的属性来存储:this.attributes,set/get都围绕this.attributes操作。
监听对象中属性的变化(change)
Models 用来创建数据,校验数据,存储数据到服务器端.Models 还可以绑定事件。比如用户动作变化触发 models 的 change 事件,所有展示此model 数据的 views 都会接收到 这个 change 事件,进行重绘。
如果任何属性的改变模型的状态,“改变”事件将触发模式
只是实现了一个自定义事件功能
监听属性color的改变
sidebar.on('change:color', function(model, color) {
console.log('修改颜色',color)
});
设置改变
sidebar.set({color: 'white'});
源码实现
Backbone.Model继承了自定义事件Events
_.extend(Model.prototype, Events, {});
sidebar实例继承了Backbone.Model.
var Sidebar = Backbone.Model.extend
所以Sidebar也具有自定义事件的功能,只是在set方法里面按照规则触发
使用 set() 方法创建或者设置属性值可以触发自定义事件,
if (!silent) {
if (changes.length) this._pending = options;
for (var i = 0, l = changes.length; i < l; i++) {
this.trigger('change:' + changes[i], this, current[changes[i]], options);
}
}
PS:
我们知道虽然属性是存储this.attributes中,但是如果是直接
实例.attributes.name = "属性名";
这样很明显就丢失了自定义事件了,所以使用 set() 是改变模型状态并触发其变更事件的唯一方法
Model 这一概念来对事件进行控制,但是这样很好的使我们将结构分离开,容易控制整体以及之后的变更都会变得异常简单。
为对象添加验证规则,以及错误提示
验证模型数据规范
var Chapter = Backbone.Model.extend({
validate: function(attrs, options) {
if (attrs.end < attrs.start) {
return "can't end before it starts";
}
}
});
源码部分
_validate: function (attrs, options) {
if (!options.validate || !this.validate) return true;
attrs = _.extend({}, this.attributes, attrs);
var error = this.validationError = this.validate(attrs, options) || null;
if (!error) return true;
this.trigger('invalid', this, error, _.extend(options, {validationError: error}));
return false;
}
执行了this.validate(attrs, options) 自定义验证函数,可见如果返回了true
就会执行this.trigger('invalid', this, error, _.extend(options, {validationError: error})); 错误通知了
余下的fetch,save,sync,url等等放在合集中在讲吧
前端MVC框架Backbone 1.1.0源码分析(二) - 模型的更多相关文章
- 前端MVC框架Backbone 1.1.0源码分析(一)
前言 如何定义库与框架 前端的辅助工具太多太多了,那么我们是如何定义库与框架? jQuery是目前用的最广的库了,但是整体来讲jQuery目的性很也明确针对“DOM操作”,当然自己写一个原生态方法也能 ...
- 前端MVC框架Backbone 1.1.0源码分析系列
Backbone.js 是一个在JavaScript环境下的 模型-视图-控制器 (MVC) 框架.任何接触较大规模项目的开发人员一定会苦恼于各种琐碎的事件回调逻辑.以及金字塔般的代码.而且,在传统的 ...
- 最轻量级的前端Mvc框架backbone
最轻量级的前端Mvc框架backbone依赖最轻量级的库understore backbone并非将前端再次切分为mvc,而是分为了七大模块,分别是:Events.Model.Collection.R ...
- 框架-springmvc源码分析(二)
框架-springmvc源码分析(二) 参考: http://www.cnblogs.com/leftthen/p/5207787.html http://www.cnblogs.com/leftth ...
- AFNetWorking3.0源码分析
分析: AFNetWorking(3.0)源码分析(一)——基本框架 AFNetworking源码解析 AFNetworking2.0源码解析<一> end
- Java并发包源码学习之AQS框架(四)AbstractQueuedSynchronizer源码分析
经过前面几篇文章的铺垫,今天我们终于要看看AQS的庐山真面目了,建议第一次看AbstractQueuedSynchronizer 类源码的朋友可以先看下我前面几篇文章: <Java并发包源码学习 ...
- drf框架,restful接口规范,源码分析
复习 """ 1.vue如果控制html 在html中设置挂载点.导入vue.js环境.创建Vue对象与挂载点绑定 2.vue是渐进式js框架 3.vue指令 {{ }} ...
- Solr5.0源码分析-SolrDispatchFilter
年初,公司开发法律行业的搜索引擎.当时,我作为整个系统的核心成员,选择solr,并在solr根据我们的要求做了相应的二次开发.但是,对solr的还没有进行认真仔细的研究.最近,事情比较清闲,翻翻sol ...
- Solr4.8.0源码分析(25)之SolrCloud的Split流程
Solr4.8.0源码分析(25)之SolrCloud的Split流程(一) 题记:昨天有位网友问我SolrCloud的split的机制是如何的,这个还真不知道,所以今天抽空去看了Split的原理,大 ...
随机推荐
- js返回顶部效果
当用户浏览的网页过于长的时候,用户在浏览到网页底部想要在返回顶部需要滚动好几次滚轮才能返回顶部,不仅麻烦,而且用户体验也会很差.现在的大多是页面都会在页面顶部或者是页面的可见区域的某一位置固定一个按钮 ...
- 让div垂直居中的5种方法
方法一: 这个方法把 div 的显示方式设置为表格,然后我们可以使用表格的 vertical-align property 属性. HTML & CSS: <div class=&quo ...
- Daily Scrum02 12.16
鉴于近期数据库大作业提交到了关键时期,大家的时间都十分的紧张,因而,我们决定全团队成员交替作业,不在每日每个成员都分配任务,而只需要每个成员保证每两天一次的工作量,以此方式给大家腾出去完成自己的事情. ...
- form data和request payload的区别
HTML <form> 标签的 enctype 属性 在下面的例子中,表单数据会在未编码的情况下进行发送: <form action="form_action.asp&qu ...
- SQL 去掉某字段括号中的值
今天在数据库匹配数据的时候,发现一些数据存在别名,导致我的数据匹配不上.在这里记录分享一下 例如: 李钟硕 (Lee Jong Suk),这里我匹配的是 “李钟硕” 示例1: SELECT rever ...
- SQL 表的完整性
建立:主外键,约束.(删除主表的时候,同时删除子表:更新主表的时候更新子表) 1.建表时定义主键 Create table 表名 ( Sno int identity(1,1), Sname nvar ...
- Javascript初学篇章_8(事件)
事件 HTML 事件是发生在 HTML 元素上的事情.例如用户点击按钮时,点击也是一个事件.事件可以用于处理表单验证,用户输入,用户行为及浏览器动作,如: 页面加载时触发事件 页面关闭时触发事件 用户 ...
- web app iphone4 iphone5 iphone6 响应式布局 适配代码
在网页中,pixel与point比值称为device-pixel-ratio,普通设备都是1,iPhone 4是2,有些Android机型是1.5.] 那么-webkit-min-device-pix ...
- java反射机制,通过类名获取对象,通过方法名和参数调
import java.lang.reflect.Method; import javax.persistence.Table; /** * 通过注解javax.persistence.Tabl ...
- QQ表情的发送与接收
我想大家对QQ表情一定不会陌生,一个个小头像极大丰富了聊天的乐趣,使得聊天不再是简单的文字叙述,还能够配上喜.怒.哀.乐等表达人物心情的小图片.本文重点要介绍的内容就是如何在微信公众平台使用QQ表情, ...