Backbone模型

Backbone模型

如今進入最關鍵的組件 - 模型。模型用來存儲應用的全部數據,以及直接和數據操做相關的邏輯。Backbone中的模型類是Backbone.Model,它包含了數據存儲,數據驗證,以及數據發生變更時觸發相關動做。javascript

通常能夠把模型與後端綁定(ORM),模型改變的同時向後端發起請求(Ajax)更新數據(數據庫)。也有把模型和DOM元素綁定,模型改變時更新HTML界面。html

 

模型

能夠直接new一個Backbone.Model,它返回一個Model實例java

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

也可擴展Backbone.Model,定義本身的模型類(構造器)數據庫

1
2
3
4
5
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的屬性函數

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

Firefox控制檯使用get方法獲取屬性post

set方法除了能夠接受對象形式參數,也能夠接受前兩個key,value方式。fetch

set方法內部對此作了兼容,第一個參數key若是是對象類型,直接將該對象拷貝到this.attributes上,若是key是字符串,那麼將在內部把key,value轉成一個臨時對象attrs再拷貝到this.attributes上。this

 

set還有第三個可選參數options,若是設置了options.validate=true,且模型若是定義了validate方法,那麼每次設置時將調用該方法進行校驗,校驗未經過將不進行後續設置,而直接返回。

1
2
3
4
5
6
7
8
9
10
11
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方法,該方法以下

1
2
3
4
5
6
7
8
_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」事件,以下

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

你能夠在回調函數中去更新視圖或處理特定的業務邏輯。若是你顯示設置第三個參數中silent爲true,將不會觸發「change」事件。

1
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,直接返回,見源碼

1
2
3
4
5
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)

以下

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

3. 能夠傳success和error兩個回調函數以處理保存成功與失敗場景

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

4. 事件,save成功後會依次觸發模型的「change」、「request」、「sync」事件。若是監聽了這些事件,那麼回調將獲得執行

 

從服務器獲取模型 - fetch

從服務器端獲取使用fetch方法,fetch方法很短

1
2
3
4
5
6
7
8
9
10
11
12
13
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。以下

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

控制檯中分別設置下name和age

能夠看到,只有設置name時才觸發事件。

 

除了Backbone.Model自身提供的事件,你還能夠給本身的Model添加自定義的事件以知足需求。

 

鳥瞰圖

1. 內部狀態,各屬性影響的方法

 

2. 構造器執行流程

相關文章
相關標籤/搜索