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

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值。


發佈了415 篇原創文章 · 獲贊 13 · 訪問量 56萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章