现在进入最关键的组件 - 模型。模型用来存储应用的所有数据,以及直接和数据操作相关的逻辑。Backbone中的模型类是Backbone.Model,它包含了数据存储,数据验证,以及数据发生变动时触发相关动作。

一般可以把模型与后端绑定(ORM),模型改变的同时向后端发起请求(Ajax)更新数据(数据库)。也有把模型和DOM元素绑定,模型改变时更新HTML界面。

模型

可以直接new一个Backbone.Model,它返回一个Model实例

var model = new Backbone.Model()
model.set({name: 'Backus', age: 35})

也可扩展Backbone.Model,定义自己的模型类(构造器)

var Person = Backbone.Model.extend({
initialize: function(name, age) {
this.set({name: name, age: age})
}
})

extend的第一个参数为一个对象,它将成为模型实例的属性。第二个参数将成为类属性(类静态属性、方法)。这在 Backbone的写类方式 有所提及。

模型与属性 - set/get

使用set和get方法来设置或获取模型的属性。属性在模型实例上有一个专门的属性来存储:this.attributes,set/get都围绕this.attributes操作。

设置模型Person的属性

var p1 = new Person()
p1.set({name: 'Backus', age: 87})

Firefox控制台使用get方法获取属性

set方法除了可以接受对象形式参数,也可以接受前两个key,value方式。

set方法内部对此做了兼容,第一个参数key如果是对象类型,直接将该对象拷贝到this.attributes上,如果key是字符串,那么将在内部把key,value转成一个临时对象attrs再拷贝到this.attributes上。

set还有第三个可选参数options,如果设置了options.validate=true,且模型如果定义了validate方法,那么每次设置时将调用该方法进行校验,校验未通过将不进行后续设置,而直接返回。

var Person = Backbone.Model.extend({
validate: function(attrs) {
if ( !_.isString(attrs.name) ) return 'name 必须是字符串类型'
if ( !_.isNumber(attrs.age) ) return 'age 必须是数字类型'
}
})
var p1 = new Person()
p1.on('invalid', function(model, error, agr) {
console.log(error)
})
p1.set({name: 'Backus', age: 87})

从控制台输入如下

可以看到输出了提示信息“name 必须是字符串类型”,再打印出p1的JSON格式

可以看到name仍然是“Backus”,并未修改。

在set方法内部会调用私有的this._validate方法,该方法如下

_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;
}

1.0与之前版本实现不同,必须显示的设置options.validate=true,且模型必须实现this.validate方法,才会进行验证,否则直接返回true。1.0之前默认就进行验证,无需设置options.validate为true。验证无效(失败)后会派发“invalid”事件,因此可以监听该事件做后续处理,比如显示一些必要的提示信息。

默认情况下,set调用都会触发“change”事件,如下

p1.on('change', function(model, error) {
console.log('attributes has changed')
})
p1.set({name: 'Backus', age: 87})

你可以在回调函数中去更新视图或处理特定的业务逻辑。如果你显示设置第三个参数中silent为true,将不会触发“change”事件。

p1.set({name: 'Backus', age: 87}, {silent: true})

从set源码可以看到,this._validate执行在前,this.trigger在后。也就是说如果验证失败,那么就不会执行change事件。

附set方法执行流程图

把模型保存到服务器 - save

save方法会把模型保存到服务器端,它的参数和set完全一致。内部调用set和sync方法。

以下几点需要注意

1. 默认会进行属性校验,即options.validate为true,校验失败将不会请求后台程序,也不会设置模型的this.attributes,直接返回,见源码

if (attrs && !options.wait) {
if (!this.set(attrs, options)) return false;
} else {
if (!this._validate(attrs, options)) return false;
}

2. 首次保存时(isNew),会采用create方式(HTTP post),已存在的model则只需要update方式(HTTP put)

如下

var p1 = new Person()
p1.save({name: 'Backus', age: 87}) // create
p1.save({name: 'John'}) // update

3. 可以传success和error两个回调函数以处理保存成功与失败场景

var p1 = new Person()
p1.save({name: 'Backus', age: 87}, {
success: function() {},
error: function() {}
})

4. 事件,save成功后会依次触发模型的“change”、“request”、“sync”事件。如果监听了这些事件,那么回调将得到执行

从服务器获取模型 - fetch

从服务器端获取使用fetch方法,fetch方法很短

fetch: function(options) {
options = options ? _.clone(options) : {};
if (options.parse === void 0) options.parse = true;
var model = this;
var success = options.success;
options.success = function(resp) {
if (!model.set(model.parse(resp, options), options)) return false;
if (success) success(model, resp, options);
model.trigger('sync', model, resp, options);
};
wrapError(this, options);
return this.sync('read', this, options);
},

1. 它使用read方式(HTTP get)

2. 请求成功后调用set方法设置模型属性(this.attributes),设置失败则直接返回不调用success,设置成功接着调用success,最后派发“sync”事件

模型的事件 - change/invalid/sync

上面已经提到的事件 change、 invalid、sync。change事件还可以只监听指定的属性,格式:"change:" + attributeName。如下

var p1 = new Person()
p1.on('change:name', function(model, error) {
console.log('name has changed')
})

控制台中分别设置下name和age

可以看到,只有设置name时才触发事件。

除了Backbone.Model自身提供的事件,你还可以给自己的Model添加自定义的事件以满足需求。

鸟瞰图

1. 内部状态,各属性影响的方法

2. 构造器执行流程

Backbone模型的更多相关文章

  1. backbone模型层浅析

    Model层有两个类: Model, Collection 1.Model 不翻文档,我们用代码说话. 首先分析下类. var myM = Backbone.Model.extend({})//构造一 ...

  2. 前端MVC框架Backbone 1.1.0源码分析(二) - 模型

    模型是什么? Models are the heart of any JavaScript application, containing the interactive data as well a ...

  3. 前端MVC框架Backbone 1.1.0源码分析系列

    Backbone.js 是一个在JavaScript环境下的 模型-视图-控制器 (MVC) 框架.任何接触较大规模项目的开发人员一定会苦恼于各种琐碎的事件回调逻辑.以及金字塔般的代码.而且,在传统的 ...

  4. 初探Backbone

    Backbone简介 中文API:http://www.csser.com/tools/backbone/backbone.js.html 英文API:http://backbonejs.org/ B ...

  5. backbone库学习-model

    backbone库的结构: http://www.cnblogs.com/nuysoft/archive/2012/03/19/2404274.html 本文所有例子来自于http://blog.cs ...

  6. 【javascript激增的思考04】MVC与Backbone.js(beta)

    前言 最近整理了很多前端面试题的东西,今天又去参加了一次面试,不知各位烦不烦,我反正有点累了,于是我们今天继续回到我们前段时间研究的问题,我们再来看看MVC吧. 什么是MVC 又回到这个问题了,到底什 ...

  7. (转)初探Backbone

    (转)http://www.cnblogs.com/yexiaochai/archive/2013/07/27/3219402.html 初探Backbone 前言 Backbone简介 模型 模型和 ...

  8. Backbone Model——数据模型

    Model是Backbone中所有数据模型的基类,用于封装原始数据,并提供对数据进行操作的方法,我们一般通过继承的方式来扩展和使用它. 如果你做过数据库开发,可能对ORM(对象关系映射)不会陌生,而B ...

  9. 转:Backbone与Angular的比较

    原文来自于:http://www.infoq.com/cn/articles/backbone-vs-angular 将不同的思想和工具进行对比,是一种更好地理解它们的方式.在本文中,我首先将列举在创 ...

随机推荐

  1. HNU 13308 Help cupid

    Help cupid Problem's Link: http://acm.hnu.cn/online/?action=problem&type=show&id=13308&c ...

  2. 使用innerHTML获取HTML代码时,HTML标记属性的双引号好多都消失不见了,原来是属性值中包含空格才会保留双引号

    最近搞的一个项目中所使用的方式比较奇怪,用Label显示HTML内容,然后不断地使用JS把Label的innerHTML复制到TextBox中. 但是,昨天发现了一个问题,获取元素值的时候,有时候正常 ...

  3. .NET程序的编译和运行

    程序的编译和运行,总得来说大体是:首先写好的程序是源代码,然后编译器编译为本地机器语言,最后在本地操作系统运行. 下图为传统代码编译运行过程: .NET的编译和运行过程与之类似,首先编写好的源代码,然 ...

  4. .net开发微信公众平台

    一.说明:公众平台信息接口为开发者提供了一种新的消息处理方式,只有申请成为开发者后,你才能使用公众平台的开发功能,在这里你需要填写一个URL和一个Token,这两项信息也需要你拥有自己的服务器(外网服 ...

  5. 重温html5的新增的标签和废除的标签

    HTML5已经盛行有段时间了,对于标签的使用,按照规范,哪些该用,哪些不该用,你是否都掌握了呢.今天我在这里详细列举下: 新增的结构标签 section元素 表示页面中的一个内容区 块,比如章节.页眉 ...

  6. SqlServer知识点记录分享

    知识点介绍 双向检索:这里就不大话概念了,直接说它的作用 ISNULL()函数:判断函数是否有值,如果变量没有赋值就给定指定的值,下面的例子就是如果@TOTALCOUNT变量为NULL那么就赋值为空字 ...

  7. 混合式APP开发中中间件方案Rexsee

    发现Rexsee时,他已经一年多没有更新过了,最后版本是2012年的. 他的实现思路是通过Android自带的Java - Javascript 桥机制,在WebView中的JavaScript同Ja ...

  8. JavaScript来实现打开链接页面(转载)

    在页面中的链接除了常规的方式以外,如果使用javascript,还有很多种方式,下面是一些使用javascript,打开链接的几种方式: 1.使用window的open方法打开链接,这里可是在制定页面 ...

  9. Javascript一些小细节

    1.判断class存在 $(obj).hasClass('BTCheck_ON') $obj.attr('class')=="BTCheck_ON" 有时我们判断样式存在会写成第二 ...

  10. 对抗静态分析——运行时修复dex

    对抗静态分析——运行时修复dex   本文来源:i春秋社区-分享你的技术,为安全加点温度 零.写在前面   这个系列本来题目想写对抗反编译,可是想想对抗反编译的这个范围有点大,总结如下 灵魂作图   ...