Backbine.js實戰第五章----模型集合

我叫阿狸貓發表於2014-11-06

5.1 建立集合物件

   在Backbone中,建立模型集合的方法十分簡單,通常分為兩種方法:一種方法是自定義集合類,再例項化集合物件;另一種方法是直接例項化集合物件。從執行效果來看,後一種方法比前一種方法在程式碼上更簡潔、更高效。

5.1.1 自定義集合物件

    集合類是依附於資料模型類,使用自定義集合物件時,首先自定義一個集合類,並在集合類中設定model屬性值來宣告模型類。然後例項化一個當前集合類的物件,就可以向該物件新增各個資料模型物件。下面通過一個簡單的示例來說明在例項化集合物件之後,新增資料模型物件的過程。   

    示例5-1 自定義集合物件

1.功能描述

    首先,定義一個資料模型類student,並在構建該類時,通過defaults屬性設定預設屬性值。然後,仍然呼叫extend擴充套件方法,以自定義的方式構建一個基於資料模型類student的資料集合類stulist。在構建集合類時,通過model屬性設定依附的模型類名稱。最後,定義一個陣列物件stumodels,用於儲存模型資料,並在例項化一個名為stus的集合物件時,將該陣列物件以實參的形式新增到物件中。集合物件會自動將這些模型資料轉化成一個個對應的模型物件,遍歷集合物件stus中的模型物件,並在遍歷過程中將各個模型物件中的內容以JSON格式輸出到瀏覽器的控制檯中。

var student = Backbone.Model.extend({
	defaults:{
		Code:"",
		Name:"",
		Score:""
	}
});	
var stulist = Backbone.Collection.extend({
	model:student
});
var stumodels = [
	{Code: "10104",Name: "張三",Score: "500"},
	{Code: "10105",Name: "李四",Score: "300"},
	{Code: "10106",Name: "王五",Score: "700"},
];
var stus = new stulist(stumodels); 
for(var i=0;i<stus.models.length;i++){
	console.log(stus.models[i].toJSON());
}

2.原始碼分析

    本示例通過extend方式自定義一個集合類stulist,並在定義該類的過程中,設定依附於本類的資料模型model屬性值。當例項化一個集合類物件,並向該物件新增資料時,集合類會自動建立model屬性值指定的資料模型,並將這些物件儲存至資料模型中。嚴格來說,這些資料模型物件實際上都儲存在集合物件的model屬性中,該屬性是一個陣列集合。因此,遍歷該陣列集合時,便可以訪問每一個模型物件,並以JSON格式的方式輸出模型物件中的資料。


5.1.2 例項化集合物件

    在示例5-1中,先自定義集合類,再例項化該類的方式實現了集合物件的定義,這種方式相對複雜些。雖然複雜,但採用extend方式自定義集合類,可以在自定義的類中擴充套件其他的屬性和方法,擴充性更強。其實,也可以通過直接例項化一個集合類的方式來實現集合物件的定義,相比而言,這種方式更加簡單。

    示例5-2 例項化集合物件

1.功能描述

    在示例5-1的基礎之上進行修改,當構建完模型類和用於填充集合物件的陣列之後,採用new例項化的方式直接定義集合物件。在定義過程中,呼叫陣列初始化集合資料,並通過配置檔案物件model屬性宣告該集合物件所依附的模型類名。

var student = Backbone.Model.extend({
	defaults:{
		Code:"",
		Name:"",
		Score:""
	}
});	
var stumodels = [
	{Code: "10104",Name: "張三",Score: "500"},
	{Code: "10105",Name: "李四",Score: "300"},
	{Code: "10106",Name: "王五",Score: "700"},
];
var stus = new Backbone.Collection(stumodels,{//這裡是和上面不同的  1.new  2.沒有extend
	model:student
});
for(var i=0;i<stus.models.length;i++){
	console.log(stus.models[i].toJSON());
}

2.原始碼分析

    在上述程式碼中,集合物件stus是通過直接例項化集合類定義的。在定義的過程中,第一個引數為新增的模型資料,該資料在定義時也會自動轉成一個個模型物件;同時,第二個引數為配置物件,通過該物件新增並設定model屬性值,集合內部將根據該屬性值自動將獲取的模型資料轉化成該屬性值的模型例項物件。其最終在chrome瀏覽器控制檯輸出效果與上圖5-1完全一樣。


5.1.3 自定義集合方法

    以自定義的方式構建集合類時,不僅可以通過model屬性指定依附的資料模型,而且還可以自定義方法。因為在集合物件中,都是針對資料的儲存和管理,集合中的方法側重於對資料的操作,例如根據規則過濾資料。接下來通過一個簡單的示例來演示集合中定義方法的過程。

    示例5-3 自定義集合方法

1.功能描述

    在構建集合模型時,除設定model屬性值外,自定義一個good方法。在該方法中,呼叫集合物件中的filter方法,只要Score大於400的模型物件,即呼叫該方法時,將返回Score屬性大於400的模型物件集合。

    此外,當例項化一個集合物件之後,通過該物件呼叫自定義的good方法,並將該方法返回的模型物件儲存到變數stug中,最後通過遍歷的方式將變數stug中的各個模型物件以JSON格式顯示在瀏覽器的控制檯中。

var student = Backbone.Model.extend({
	defaults:{
		Code:"",
		Name:"",
		Score:""
	}
});	
var stulist = Backbone.Collection.extend({
	model:student,
	good:function(){
		return this.filter(function(stu){
			return stu.get("Score")>400;
		});
	}
});
var stumodels = [
	{Code: "10104",Name: "張三",Score: "500"},
	{Code: "10105",Name: "李四",Score: "300"},
	{Code: "10106",Name: "王五",Score: "700"},
];
var stus = new stulist(stumodels);
var stug = stus.good();
for(var i=0;i<stug.length;i++){
	console.log(stug[i].toJSON());
}


2.原始碼分析

    從上圖中可以看出,由於是遍歷顯示Score屬性值於大於400的模型物件,當呼叫good方法時,資料模型集合又進行了一次過濾,返回符合條件的模型物件。在資料模型集合中存在一個Score屬性值為300的模型物件,不符合過濾規則,因此該模型物件沒有出現在模型物件集合中。



5.2 操作集合中模型物件

    在上一節中介紹了定義集合物件的方法,當一個集合物件定義完成之後,它所包含的都是定義時的一個個資料模型物件。這些模型物件也可以通過集合類提供的方法進行移除,也能呼叫新增模型物件的方法進行再次增加。在移除或增加時,將會自動觸發remove或add事件。此外,還可以針對集合中模型物件進行查詢和排序的操作。

5.2.1 移除集合物件中的模型

     集合類中提供了3種移除集合物件中模型的方法,分別為remove、pop、shift,它們的使用方法如下。

    (1)remove方法的功能是從指定的集合物件中移除一個或多個模型物件,該方法的呼叫格式如下。

     obj.remove(models,options)

      其中,obj為例項化後的集合物件,models為一個或多個模型物件,options為配置物件,可以在該物件中設定slient屬性等。

    (2)pop方法的功能是移除集合物件中最後一個模型物件,該方法的呼叫格式如下。

     obj.pop(options)

    (3)shift方法的功能是移除集合物件中首個模型物件,該方法的呼叫格式如下。

     obj.shift(options)

     在上述pop和shift方法的呼叫格式中,各引數與remove的功能一樣,不在贅述。接下來通過一個簡單的示例來介紹這些方法的使用過程,

    示例5-4 移除集合物件中的模型

1.功能描述

    在本示例中,首先使用shift方法刪除第一條模型物件。然後使用remove方法刪除第四條模型物件,即索引號為3(因為索引號預設從0開始)。最後使用pop方法刪除最後一條模型物件,並遍歷剩餘的模型物件資料,以JSON格式在瀏覽器的控制檯中輸出各個模型物件的內容。

var student = Backbone.Model.extend({
	defaults:{
		Code:"",
		Name:"",
		Score:""
	}
});	
var stumodels = [{
    Code: "10101",
    Name: "劉真真",
    Score: 530
}, {
    Code: "10102",
    Name: "張明基",
    Score: 460
}, {
    Code: "10103",
    Name: "舒虎",
    Score: 660
}, {
    Code: "10104",
    Name: "周小敏",
    Score: 500
}, {
    Code: "10105",
    Name: "陸明明",
    Score: 300
}, {
    Code: "10106",
    Name: "佔小方",
    Score: 380
}, {
    Code: "10107",
    Name: "陳天豪",
    Score: 720
}];
var stus = new Backbone.Collection(stumodels,{
	model:student
});
//刪除第1條模型物件
stus.shift();
//刪除第4條模型物件
stus.remove(stus.models[3]);
//刪除最後一條模型物件
stus.pop();
//重新輸出全部的模型物件
for(var i=0;i<stus.models.length;i++){
	console.log(stus.models[i].toJSON());
}

2.原始碼分析

    從上圖中可以看出,有下劃線的資料都被刪除。首先,刪除第一條,即Code屬性值為10101的模型物件;然後刪除第四條,即索引號為3的模型物件,在刪除第一條的基礎之上,這條記錄就指向了Code屬性值為10105的模型物件。最後刪除最後一條,即Code屬性值為10107的模型物件。這個示例說明,在每次按順序刪除模型物件後,內部的模型物件集合都會重排索引號。

5.2.2 新增集合物件中的模型

   上一節中介紹瞭如何刪除集合物件中的模型方法,集合的類中還提供了與刪除方法相對應增加集合物件模型的方法,用於新增模型物件,實現的方法提供了以下幾種。

   (1)add方法與remove方法對應,功能是向集合物件中指定的位置插入模型物件,沒有指定位置,預設為集合物件的尾部。該方法的呼叫格式如下。

     obj.add(models,options)

   (2)push方法與pop方法對應,功能是向集合物件的尾部插入模型物件。它的功能與add方法類似,只是明確了是插入尾部位置,該方法的呼叫格式如下。

    obj.push(models,iptions)

   (3)unshift方法與shift方法對應,功能是向集合物件的頭部插入模型物件。它的功能和push方法類似,只是插入的位置不同,該方法的呼叫格式如下。

    obj.unshift(models,options)

    以上三種方式使用的引數與add使用的引數說明基本相同,不在贅述。接下來通過一個簡單的示例來介紹這些方法的使用過程。

    示例5-5 新增集合物件中的模型

1.功能描述

    首先,定義兩個陣列物件stumodels和newmodels,前者用於定義集合物件時注入的原始資料,後者用於集合物件呼叫新增方法新增模型物件時的資料。例項化一個集合物件stus,然後,分別呼叫unshift、add、push方法向集合物件stus中新增模型物件。最後,遍歷整個新增模型物件之後的資料,以JSON格式在瀏覽器的控制檯中輸出各個模型物件的內容。

var student = Backbone.Model.extend({
	defaults:{
		Code:"",
		Name:"",
		Score:""
	}
});	
var stumodels = [{
    Code: "10101",
    Name: "劉真真",
    Score: 530
}, {
    Code: "10102",
    Name: "張明基",
    Score: 460
}, {
    Code: "10103",
    Name: "舒虎",
    Score: 660
}, {
    Code: "10104",
    Name: "周小敏",
    Score: 500
}, {
    Code: "10105",
    Name: "陸明明",
    Score: 300
}, {
    Code: "10106",
    Name: "佔小方",
    Score: 380
}, {
    Code: "10107",
    Name: "陳天豪",
    Score: 720
}];
var newmodels = [{
    Code: "10108",
    Name: "李煜",
    Score: 570
}, {
    Code: "10109",
    Name: "鍾舒暢",
    Score: 460
}, {
    Code: "10110",
    Name: "佟明月",
    Score: 680
}];
var stus = new Backbone.Collection(stumodels,{
	model:student
});
//在頭部位置插入模型物件
stus.unshift(newmodels[1]);
//在索引號為5的位置插入模型物件
stus.add(newmodels[0],{at:5});
//在尾部位置插入模型物件
stus.push(newmodels[2]);
//重新輸出全部的模型物件
for(var i=0;i<stus.models.length;i++){
	console.log(stus.models[i].toJSON());
}

2.原始碼分析

    從上圖中可以看出,有下劃線的資料都是新新增的。首先,使用unshift方法在頭部位置插入模型物件時,便新增了Code屬性值為10109的模型物件;然後集合物件stus內部重置索引號,當呼叫add方法在集合物件索引號為5的位置插入模型物件,則新增Code屬性為10108的模型物件;最後,呼叫集合物件的push方法向模型物件的尾部位置插入模型物件時,便新增Code屬性值為10110的模型物件。


5.2.3 查詢集合物件中的模型

    上節介紹瞭如何在集合物件中刪除和新增模型物件的方法,除此之外,還可以通過集合類中提供的get、at、findWhere、where方法,查詢集合中的一個或多個模型物件,接下來詳細地介紹這些方法的使用過程。

    (1)get方法的功能是通過指定的ID號獲取集合中的某一個模型物件,它的呼叫格式如下。

     obj.get(id)

    其中,obj為例項化後的集合物件,引數ID為模型物件在產生時的唯一標誌,也是用於與伺服器保持同步的唯一編號,它的正式名稱為小寫的ID,如果在構建模型物件類中,沒有該屬性,也可以通過idAttribute屬性值指定其他數字型別的屬性為id標誌,一旦某屬性被指定為id標誌,它將過濾重複的屬性值,不能增加與該屬性值相同的模型物件。

    (2)at方法的功能是通過指定的索引號獲取集合中的某一個模型物件,它的呼叫格式如下。

     obj.at(index)

     其中,obj為例項化後的集合物件,引數index為集合物件中模型資料的索引號,該索引號以0開始,最大值為obj.models,length-1。

    (3)findWhere方法的功能是查詢與屬性名稱和屬性值相匹配的第一個模型物件,呼叫格式如下。

     obj.findWhere(attrs)

    其中,除了obj為例項化後的集合物件外,引數attrs為key/value形式的屬性值物件,attrs引數只能新增一個組key/value形式的屬性值,多組屬性值以最後一組為準

    (4) where方法的功能是查詢與屬性名稱和屬性值相匹配的第一個模型或多個模型物件。與findWhere方法相比,通過新增加的引數可以決定它查詢時返回的物件模型數量,呼叫格式如下。

     obj.where(attrs,first)

     其中,引數attrs與findWhere方法的使用說明相同。而新增加的first引數是一個布林型別的值,當該引數為true時,表示返回與屬性名稱和屬性值相匹配的第一個模型物件,這時的功能與findWhere方法相同;而當該引數為false時,表示返回與屬性名稱和屬性值相匹配的全部模型物件,是一個陣列集合。

    示例5-6 查詢集合物件中的模型

1.功能描述

    首先,以JSON格式輸出集合中全部模型物件的內容,作為接下來查詢操作的參考資料。然後,開始查詢模型物件時,分別呼叫get、at、findWhere、where方法獲取查詢後的模型物件,並儲存在不同變數中。最後,在瀏覽器的控制檯分別以JSON格式輸出這些變數的內容。

var student = Backbone.Model.extend({
	defaults:{
		Code:"",
		Name:"",
		Score:""
	},
	idAttribute:"Code"
});	
var stumodels = [{
    Code: "10101",
    Name: "劉真真",
    Score: 530
}, {
    Code: "10102",
    Name: "張明基",
    Score: 660
}, {
    Code: "10103",
    Name: "舒虎",
    Score: 660
}, {
    Code: "10104",
    Name: "周小敏",
    Score: 500
}, {
    Code: "10105",
    Name: "陸明明",
    Score: 300
}, {
    Code: "10106",
    Name: "佔小方",
    Score: 380
}, {
    Code: "10107",
    Name: "陳天豪",
    Score: 720
}];
var stus = new Backbone.Collection(stumodels,{
	model:student
});
//輸出全部的模型物件
for(var i=0;i<stus.models.length;i++){
	console.log(stus.models[i].toJSON());
}
console.log("---------------------------查詢結果---------------------------");		
//查詢ID號為10106的物件模型
var find_id_model = stus.get(10106);
//查詢索引號為6的物件模型
var find_at_model = stus.at(6);
//查詢與屬性名稱和值相匹配的物件模型
var find_0_model = stus.findWhere({
	Score:660
});
var find_1_model = stus.where({
	Score:660
},true);
var find_2_model = stus.where({
	Score:660
},false);
//以物件的形式輸出模型內容
console.log(find_id_model.toJSON());
console.log(find_at_model.toJSON());
console.log(find_0_model.toJSON());
console.log(find_1_model.toJSON());
console.log("---------------------------陣列結果---------------------------");
for(var i=0;i<find_2_model.length;i++){
	console.log(find_2_model[i].toJSON());
}

2.原始碼分析

    首先使用集合物件的get方法查詢集合物件中ID號為10106的模型物件。在模型類中通過idAttribute將Code屬性值指定為ID號屬性,因此get方法將查詢Code屬性值為10106的模型物件,執行效果如上圖中查詢結果區域的第一行所示。

    然後,使用集合物件的at方法查詢集合物件中索引號為6的模型物件,由於索引號是從0開始的,因此該方法將獲取Code屬性值為10107的模型物件,執行效果如上圖中查詢結果區域的第二行所示。

    最後,使用集合物件的where方法匹配與給定屬性名稱和值相同的物件,儘管有兩個物件的Score屬性值為660,但由於where方法僅返回首個與給定條件相匹配的物件,因此,該方法將獲取首個模型物件,即Code屬性值為10102的模型物件,執行效果如上圖中查詢結果區域的第三行所示。

    集合物件兩次呼叫findWhere方法匹配與給定屬性名稱和值相同的物件。第一次呼叫時,將方法的第二次引數設定為true,表示只獲取相匹配的首個模型物件,因此返回Code屬性值為10102的模型物件,執行效果如上圖中查詢結果區域的第四行所示。

    第二次呼叫時,將方法的第二個引數設定外false,表示只獲取相匹配的模型物件集合,因此,通過遍歷這個儲存在查詢結果find_2_model的變數,並以JSON格式輸出全部的模型物件內容,執行效果如上圖中查詢結果區域的第五、六行所示。

5.2.4 集合中模型物件的排序

    在上一節中介紹瞭如何查詢集合中的模型物件,此外,集合類還提供了對集合中模型物件排序的功能,只需要呼叫sort方法,其呼叫格式如下。

    obj.sort(options);

    其中,obj為例項化後的集合物件,options引數為排序過程中的配置物件,在該物件中可以設定slient等屬性。在集合物件呼叫sort方法之前,必須在例項化集合物件時新增一個名為“comparator”的方法。如果不新增該方法,可呼叫sort方法的話,會提示“Cannot sort a set without a comparator”異常資訊。

    在新增comparator方法時,需要設定兩個引數model_1和model_2,分別對應兩個相鄰的模型物件。通過兩個模型物件的排序屬性值的比較,設定按該屬性名稱排序的順序。如果按升序排列,當前者大於後者時,返回1值;如果按降序排列,當前者大於後者時,返回0值;當呼叫集合物件執行sort方法時,則按該返回值進行排序。

    集合物件的sort方法功能十分強大,全部的排序操作功能都是自動完成的,且無論是新增或移除集合中的任意模型物件後,該方法又將自動被呼叫,對集合中的全部模型物件又將按照排序規則進行重新排序,以確定排序的延續性。接下來通過一個簡單的示例來介紹該方法的使用過程。

    示例5-7 集合中模型物件的排序

1.功能描述

    首先,例項化集合物件stus時定義comparator方法,在該方法中,設定集合中模型物件按Score屬性值的降序排列。然後,呼叫集合物件的sort方法進行排序,並將排序後的全部模型物件以JSON格式輸出至瀏覽器的控制檯中。最後,呼叫集合物件的remove方法先移除集合中索引號為3的模型物件,再呼叫add方法新增一個模型物件。經過這兩次操作之後,再次將排序後的全部模型物件以JSON格式輸出至瀏覽器的控制檯中。

var student = Backbone.Model.extend({
	defaults:{
		Code:"",
		 Name:"",
		 Score:0
	},
	idAttribute:"Code"
});
var stumodels = [{
    Code: "10101",
    Name: "劉真真",
    Score: 530
}, {
    Code: "10102",
    Name: "張明基",
    Score: 460
}, {
    Code: "10103",
    Name: "舒虎",
    Score: 660
}, {
    Code: "10104",
    Name: "周小敏",
    Score: 500
}, {
    Code: "10105",
    Name: "陸明明",
    Score: 300
}, {
    Code: "10106",
    Name: "佔小方",
    Score: 380
}, {
    Code: "10107",
    Name: "陳天豪",
    Score: 720
}];
var stus = new Backbone.Collection(stumodels,{
	model:student,
	comparator:function(model_1,model_2){
		var intcomp = model_1.get("Score")>model_2.get("Score");
		return intcomp?0:1;
	}
});
stus.sort();
//增加和刪除模型前排序輸出全部的模型物件
for(var i=0;i<stus.models.length;i++){
	console.log(stus.models[i].toJSON());
}
stus.remove(stus.models[3]);
stus.add({
	Code:"10108",
	Name:"李昱",
	Score:570
});
console.log("---------------排序結果---------------");
//增加和刪除模型後排序輸出全部的模型物件
for(var i=0;i<stus.models.length;i++){
	console.log(stus.models[i].toJSON());
}

2.原始碼分析

    從上圖中可以看出,無論是刪除集合中索引號為3的模型物件,還是向集合中新增一個新的模型物件,首次排序的規則依然不變化。當集合物件在刪除或增加一個模型物件時,會自動再次呼叫排序規則的comparator方法,重新按規定的規則進行模型排序,執行效果圖上圖所示。


注意:

    集合物件的sort方法功能雖然強大,但在使用過程中需要注意兩個問題。

    第一是執行效率,由於每一次的集合模型物件變化都會引發重新排序,如果展示的集合物件數量很大,這會導致在排序的時候執行效率變得很慢,建議這個方法不要針對大量模型物件使用。

    第二是遮蔽其他按位置插入或刪除模型物件的功能,即如果呼叫了集合物件中的sort方法,前面小節中所介紹的按at屬性值插入或刪除模型物件的功能將會無效。


5.3 與伺服器互動集合中的模型物件

    在Backbone中,集合中的模型物件與上一章中的模型物件一樣,都可以呼叫內容提供的方法與伺服器進行互動。集合類中提供了fetch和create兩個方法與伺服器進行資料互動,fetch方法用於從伺服器介面獲取集合物件初始化的資料,create方法用於將建立好的集合物件中的全部模型物件資料傳送到伺服器,完成資料同步的功能。

5.3.1 呼叫fetch方法獲取伺服器資料

    與資料模型物件類似,集合物件也可以通過呼叫本身類中提供的fetch方法與伺服器進行互動, 獲取伺服器返回的資料,其呼叫格式如下所示。

    obj.fetch(options)

    其中,引數obj為集合物件,options為與伺服器進行互動過程的配置物件。在該物件中,可以新增success方法,表示當與伺服器互動成功後將會呼叫該方法。此外,當集合物件與伺服器的資料互動成功,即呼叫了自定義的success方法時,還會觸發集合物件的reset事件。但該事件不會自動觸發,需要在fetch方法的options物件中將reset屬性值設定為true,否則不會觸發。在該事件中,可以進一步對獲取的資料進行下一步的操作,例如顯示在頁面或進行儲存。接下來通過一個簡單的示例介紹該方法的使用過程。

    示例5-8 呼叫fetch方法獲取伺服器資料

1.功能描述

     首先,採用extend方法構建一個名為stulist的集合類,並在該類的建構函式initialize中,使用on方法繫結類別物件的rest事件。當觸發該事件時,將遍歷傳回的資料集合,並以JSON格式在瀏覽器的控制檯輸出全部模型物件。此外,在集合類中設定url屬性,用於設定與伺服器請求時的路徑。

    然後,例項化一個名為stus的集合物件,並呼叫fetch方法與伺服器進行資料互動,在呼叫fetch方法過程中,為了能夠在成功獲取伺服器資料時觸發reset事件,必須將reset屬性值設定為true。此外,新增success方法,當成功獲取伺服器資料時,將會執行該方法中的程式碼將獲取的資料進行遍歷,並以JSON格式的方式輸出全部的模型物件。

var student = Backbone.Model.extend({
	defaults:{
		Code:"",
		Name:"",
		Score:0
	}
});
var stulist = Backbone.Collection.extend({
	initialize:function(){
		console.log("-----reset事件觸發-----");
		this.on("reset",function(render){
			for(var i=0;i<render.models.length;i++){
				console.log(render.models[i].toJSON());
			}
		});
	},
	model:student,
	url:"../servlet/StudentListServlet"
});
var stus = new stulist();
stus.fetch({
	reset:true,
	success:function(collection,resp,options){
		console.log("-----請求成功時觸發-----");
		for(var i=0;i<collection.models.length;i++){
			console.log(collection.models[i].toJSON());
		}
	}
});

2.原始碼分析

    從上圖中可以看出,當請求定義的url屬性值獲取資料時,如果在fetch()方法中將reset屬性值設為true,當資料獲取成功時,會優先觸發已繫結的reset事件。在該事件中,通過返回的集合物件引數,可以獲取伺服器中全部的模型物件資料;當完成reset事件觸發之後,再執行success方法,在該方法中,同樣也可以返回物件引數,獲取伺服器中的模型物件資料。



5.3.2 呼叫create方法與伺服器同步資料

    在Backbone中,集合物件的create方法與模型物件的save方法相似,都是向伺服器傳送模型物件,進行資料同步操作。而集合物件在呼叫create方法時,先根據物件本身所依附的模型類新建一個模型物件,當與伺服器資料同步成功後,再將該新建的模型物件新增至集合物件中。create方法的呼叫格式如下所示。

    obj.create(model,options)

    其中,引數obj為集合物件,model引數為傳送給伺服器的模型物件,引數options則為傳送時的方法配置物件。

    在集合物件呼叫create方法過程中,會使用POST和PUT兩種請求方法向伺服器傳送資料,前者表示建立模型物件,後者則為修改模型物件。此外,集合物件呼叫create方法後,如果繫結集合物件的add事件,還會自動觸發該事件。

    另外,在集合物件呼叫create方法時,可以通過方法的配置物件設定一些與傳送相關的屬性,如新增success方法和wait、silent屬性,用於控制客戶端與伺服器同步過程中的一些操作。此外,當集合物件呼叫create方法向伺服器傳送資料時,會通過模型內容的isNew方法檢測資料是否是新建還是更新,如果是新建,會使用POST方式,否則使用PUT方式。接下來分別進行說明。

    示例5-9 POST和PUT方式傳送資料

1.功能描述

    首先定義一個名為student的模型類,使用defaults屬性設定預設的屬性項。然後使用extend方式定義一個名為stulist的集合類,在定義集合類時,使用model屬性設定所依附模型類的名稱,url屬性設定與伺服器同步資料的地址。最後例項化一個名為stus的集合物件,呼叫該物件的create方法向伺服器傳送模型物件,進行資料同步。

var student = Backbone.Model.extend({
	defaults:{
		Code:"10001",
		Name:"張三",
		Score:100
	}
});
var stulist = Backbone.Collection.extend({
	model:student,
	url:"../servlet/Servlet5_9"
});
var stus = new stulist();
stus.create({
	Code:"10107",
	Name:"皮卡丘",
	Score:750
});

2.原始碼分析

    從上圖可以看出,當客戶端以POST方式向伺服器傳送模型物件時,伺服器成功返回200,表示請求成功,也成功向客戶端返回了JSON格式的code值。由於本地客戶端在傳送物件模型時並未指定模型的ID號,則以POST方式向伺服器傳送資料,表示建立模型物件。如果在傳送資料時指定了模型ID號,則將以PUT方式向伺服器傳送資料。將示例5-9模型類進行如下程式碼修改。

var student = Backbone.Model.extend({
	defaults:{
		Code:"10001",
		Name:"張三",
		Score:100
	},
	idAttribute:"Code"
});

    上述程式碼中在定義模型類時,通過idAttribute指定模型的ID號屬性名稱為Code,因此,在呼叫集合物件的create方法建立併傳送模型物件時將攜帶ID號,即Code屬性值一併傳送。此時,傳送的方式為PUT,表示更新模型物件。最終在控制檯輸出效果如上。從上圖中可以看出,當使用PUT方式向伺服器傳送資料時,請求的URL地址後面自動新增傳送的模型物件的ID號,此時的資料發請求為更新模型物件。

注意:

    無論使用哪種方法向伺服器傳送資料,都會將已同步的模型物件資料新增到集合物件中。因為在呼叫集合物件的create方法時,如果繫結集合物件的add事件,將會自動觸發。在該事件中,可以通過呼叫集合物件,檢視全部已傳送的模型物件資料。

    示例5-10 觸發集合的add事件

1.功能描述

    在本示例中,當定義集合類時,在建構函式中繫結名為“add”的新增模型物件事件。當集合物件在新增模型物件時,將會觸發該事件。在該事件中,將在瀏覽器的控制檯以JSON格式輸出新增的模型物件內容。

var student = Backbone.Model.extend({
	defaults:{
		Code:"10001",
		Name:"張三",
		Score:100
	},
	idAttribute:"Code"
});
var stulist = Backbone.Collection.extend({
	initialize:function(){
		this.on("add",function(model,response,options){
			console.log(stus.models[0].toJSON());
		});
	},
	model:student,
	url:"../servlet/Servlet5_9"
});
var stus = new stulist();
stus.create({
	Code:"10107",
	Name:"皮卡丘",
	Score:750
});

2.原始碼分析

    當集合物件stus呼叫create方法完成與伺服器資料交之後,由於向集合物件stus自動新增了與伺服器同步的模型物件,觸發繫結的add事件,根據返回的model引數獲取已傳送的模型物件,並以JSON的格式在瀏覽器的控制檯輸出。詳細效果如上圖第一行。

    在前面提到過,當一個集合物件在通過呼叫create方法完成與伺服器資料同步之後,預設情況下,會自動將已同步後的模型物件新增到這個集合物件中。但也可以通過設定create方法中配置物件(options)的屬性值來改變這個預設過程。

    當呼叫create方法並將配置物件的wait屬性值設為true時,表示只有當客戶端與伺服器資料成功同步之後,才能將傳送的模型物件新增至集合物件中。如果將wait屬性值設為false或不新增該屬性時,則直接將傳送的模型物件新增至集合物件中。

    此外,當silent屬性值設定為true時,表示不管客戶端與伺服器是否成功完成同步資料的操作,都會將傳送的模型物件新增至集合物件中。如果將silent屬性值設為false或不新增該屬性時,只有當客戶端與伺服器成功完成資料同步之後,才會將傳送的模型物件新增至集合物件中。

    示例5-11 設定wait和silent屬性

1.功能描述

    本示例與示例5-10相比,首先修改集合類中url屬性,將該屬性值修改為一個不能正確請求的url地址。其次,在集合物件呼叫的create方法中,通過第二個引數——配置物件新增wait屬性和success方法,並將wait屬性值設定為true,在success方法中,將伺服器返回的JSON格式值輸出至瀏覽器的控制檯中。如果不新增wait屬性或將wait屬性值設定為false時,瀏覽器控制檯輸出的結果又不相同。

var student = Backbone.Model.extend({
	defaults:{
		Code:"10001",
		Name:"張三",
		Score:100
	},
	idAttribute:"Code"
});
var stulist = Backbone.Collection.extend({
	initialize:function(){
		this.on("add",function(model,response,options){
			console.log(stus.models[0].toJSON());
		});
	},
	model:student,
	url:"../servlet/Servlet115_9"
});
var stus = new stulist();
stus.create({
	Code:"10107",
	Name:"皮卡丘",
	Score:750
},{
	wait:false,
	success:function(model,response,options){
		console.log(response.changed.code);
	}
});


2.原始碼分析

    由於與伺服器的資料同步地址異常,無法完成客戶端與伺服器的資料同步操作,因此瀏覽器返回404程式碼。此外,在呼叫create方法時,通過配置物件新增了wait屬性,並將該屬性值設定為true,表示只有當客戶端與伺服器成功完成資料同步之後,才會將同步的模型物件資料新增至集合物件中。因此,同步資料異常時進行資料新增操作,也不會觸發繫結的集合物件的add事件。效果如上圖所示。

    集合物件在呼叫create方法時,不新增wait或將該屬性的值設定為false時,表示不管客戶端與伺服器的資料是否同步成功,都會將同步的模型物件資料新增至集合物件中。因此,將觸發集合物件繫結的add事件,在瀏覽器的控制檯中輸出同步的模型物件,效果如圖所示。

    除了在create方法的配置物件中新增wait屬性外,還可以新增silent屬性,但它們的作用正好相反。如果新增silent屬性並將該屬性值設定為true,屬於靜默式同步,不需要客戶端與伺服器資料同步成功,就可以向集合物件新增模型資料,與不新增wait屬性或將該屬性值設定為false時的效果一樣。

    此外,當集合物件呼叫create方法併成功與伺服器同步資料時,將會執行配置物件中新增的success方法。在該方法中,可以通過返回的changed物件獲取伺服器傳回的code值。


相關文章