數(shù)據(jù)綁定
數(shù)據(jù)綁定是在應(yīng)用程序 UI 與數(shù)據(jù)源建立連接的過(guò)程规伐。如果綁定正確數(shù)據(jù),則當(dāng)數(shù)據(jù)更改其值時(shí)枚荣,綁定到數(shù)據(jù)的UI屬性值會(huì)自動(dòng)反映更改灵再。AppWorker支持靈活的數(shù)據(jù)綁定,使UI展示和數(shù)據(jù)可以清晰的分離奴艾。目前還不支持雙向綁定净当,只支持?jǐn)?shù)據(jù)到展示的傳遞。
使用AppWorker開(kāi)發(fā)App蕴潦,你可以不使用任何數(shù)據(jù)bind機(jī)制像啼,傳統(tǒng)的獲取對(duì)象,給對(duì)象每一個(gè)單個(gè)屬性設(shè)置值也可以實(shí)現(xiàn)所有功能潭苞。但是使用bind機(jī)制可以減少代碼埋合,優(yōu)化框架,使開(kāi)發(fā)工作事半功倍萄传。
1.基本綁定方式:
bind包括源和目標(biāo)甚颂,AppWorker的bind目標(biāo)通常指UI組件,所有的UI組件都支持基本的bind方式秀菱。實(shí)際上只要一個(gè)組件有屬性就可以支持bind振诬,比如UI和MM(MultitonModule)組件都有屬性,都支持bind衍菱。
bind的源我們目前提供了2個(gè)組件do_ListData
和do_HashData
分別表示二種數(shù)據(jù)結(jié)構(gòu)赶么,hash和array,因?yàn)檎麄€(gè)AppWorker的數(shù)據(jù)基礎(chǔ)都是json格式脊串,所以這2個(gè)數(shù)據(jù)組件都是只能處理json格式辫呻。
UI和MM類的基類都提供了3個(gè)相關(guān)的方法來(lái)實(shí)現(xiàn)bind機(jī)制。
-
setMapping
方法:設(shè)置一個(gè)UI組件或者M(jìn)M組件的屬性和數(shù)據(jù)的映射關(guān)系琼锋。 -
bindData
方法:設(shè)置UI組件或者M(jìn)M組件的數(shù)據(jù)源放闺,這個(gè)數(shù)據(jù)源目前只能是do_ListData
和do_HashData
. -
refreshData
方法:當(dāng)bind的數(shù)據(jù)源數(shù)據(jù)發(fā)生變化后,調(diào)用這個(gè)方法來(lái)刷新數(shù)據(jù)源的展示缕坎。
示例如下:
function test1() {
// 創(chuàng)建一個(gè)HashData對(duì)象
var data = mm("do_HashData");
// 給Button創(chuàng)建一個(gè)屬性到數(shù)據(jù)的映射,其中text和bgColor是Button的2個(gè)屬性
btn1.setMapping({
"text" : "text_key",
"bgColor" : "color_key"
});
// 建立Button和HashData的綁定
btn1.bindData(data);
// 數(shù)據(jù)變化驅(qū)動(dòng)UI屬性變化
// 1. 修改數(shù)據(jù)
data.addData({
"text_key" : "映射到HashData",
"color_key" : "FF0022AA"
});
// 2. 刷新UI,這個(gè)按鈕的文本變成“映射到HashData”怖侦,背景顏色變?yōu)椤癋F0022AA"
btn1.refreshData();
}
其中一個(gè)UI的映射可以作為bindData的一個(gè)參數(shù),比如
function test2() {
// 創(chuàng)建一個(gè)HashData對(duì)象
var data = mm("do_HashData");
// 建立Button和HashData的綁定,同時(shí)設(shè)置映射關(guān)系
btn2.bindData(data, {
"text" : "text_key",
"bgColor" : "color_key"
});
// 數(shù)據(jù)變化驅(qū)動(dòng)UI屬性變化
// 1. 修改數(shù)據(jù)
data.addData({
"text_key" : "映射到HashData-直接設(shè)置映射",
"color_key" : "FFCC00AA"
});
// 2. 刷新UI,這個(gè)按鈕的文本變成“映射到HashData-直接設(shè)置映射”谜叹,背景顏色變?yōu)椤癋FCC00AA"
btn2.refreshData();
}
// ...
其中HashData對(duì)象支持path匾寝,中間用.號(hào)來(lái)隔開(kāi),比如
function test3() {
// 創(chuàng)建一個(gè)HashData對(duì)象
var data = mm("do_HashData");
// 給Button創(chuàng)建一個(gè)屬性到數(shù)據(jù)的映射,其中text和bgColor是Button的2個(gè)屬性
// HashData對(duì)象支持path荷腊,中間用.號(hào)來(lái)隔開(kāi)
btn3.setMapping({
"text" : "node1.text_key",
"bgColor" : "node1.color_key"
});
// 建立Button和HashData的綁定
btn3.bindData(data);
// 數(shù)據(jù)變化驅(qū)動(dòng)UI屬性變化
// 1. 修改數(shù)據(jù)
data.addData({
"node1" : {
"text_key" : "映射到HashData-支持path",
"color_key" : "F00FEEAA"
},
"node2" : "xxxx"
});
// 2. 刷新UI,這個(gè)按鈕的文本變成“映射到HashData-支持path”艳悔,背景顏色變?yōu)椤癋00FEEAA"
btn3.refreshData();
}
其中數(shù)據(jù)源也支持ListData,中間用:加數(shù)字索引來(lái)表明是一個(gè)list的一個(gè)元素
function test4() {
// 創(chuàng)建一個(gè)HashData對(duì)象
var data = mm("do_HashData");
// 給Button創(chuàng)建一個(gè)屬性到數(shù)據(jù)的映射,其中text和bgColor是Button的2個(gè)屬性
// HashData對(duì)象支持json array,中間用:加數(shù)字索引來(lái)表明是一個(gè)array的一個(gè)元素
btn4.setMapping({
"text" : "node1:2.text_key",
"bgColor" : "node1:2.color_key"
});
// 建立Button和HashData的綁定
btn4.bindData(data);
// 數(shù)據(jù)變化驅(qū)動(dòng)UI屬性變化
// 1. 修改數(shù)據(jù)
data.addData({
"node1" : [ {
"text_key" : "我是Button1",
"color_key" : "FFFFEEAA"
}, {
"text_key" : "我是Button2",
"color_key" : "FFFFEEBB"
}, {
"text_key" : "映射到HashData-支持JSONArray",
"color_key" : "00FFEECC"
} ],
"node2" : "xxxx"
});
// 2. 刷新UI,這個(gè)按鈕的文本變成“映射到HashData-支持JSONArray”女仰,背景顏色變?yōu)椤?0FFEECC"
btn4.refreshData();
}
function test5() {
// 創(chuàng)建一個(gè)ListData對(duì)象
var data = mm("do_ListData");
// 給Button創(chuàng)建一個(gè)屬性到數(shù)據(jù)的映射,其中text和bgColor是Button的2個(gè)屬性
// do_ListData對(duì)象支持:加數(shù)字索引來(lái)表明是一個(gè)array的一個(gè)元素
btn5.setMapping({
"text" : ":2.text_key",
"bgColor" : ":2.color_key"
});
// 建立Button和HashData的綁定
btn5.bindData(data);
// 數(shù)據(jù)變化驅(qū)動(dòng)UI屬性變化
// 1. 修改數(shù)據(jù)
data.addData([ {
"text_key" : "我是Button1",
"color_key" : "FFFFEEAA"
}, {
"text_key" : "我是Button2",
"color_key" : "FFFFEEBB"
}, {
"text_key" : "映射到ListData",
"color_key" : "0FF11ECC"
} ]);
// 2. 刷新UI,這個(gè)按鈕的文本變成“映射到HashData-支持JSONArray”猜年,背景顏色變?yōu)椤?0F11ECC"
btn5.refreshData();
}
其中bind目標(biāo)UI也支持path香府,中間用.隔開(kāi),只不過(guò)有一個(gè)限制就是這個(gè)時(shí)候的綁定目標(biāo)UI必須是這個(gè)ui文件的根節(jié)點(diǎn)码倦。這種情況應(yīng)用更靈活方便企孩,不需要為每一個(gè)UI創(chuàng)建一個(gè)映射和一個(gè)數(shù)據(jù)源,這個(gè)ui文件里所有UI組件可以共用一個(gè)映射和數(shù)據(jù)源袁稽。比如
function test6() {
// 根據(jù)統(tǒng)配符$來(lái)獲取ui文件的根節(jié)點(diǎn)勿璃,也可以根據(jù)它的ID獲取對(duì)象
var rootview = ui("$");
// 創(chuàng)建一個(gè)HashData對(duì)象
var data = mm("do_HashData");
// 給rootview創(chuàng)建多個(gè)子UI的屬性到數(shù)據(jù)的映射,其中button_id1.text和label_id1.text
// 分別表示這個(gè)ui文件里一個(gè)id為button_id1的Button組件和id為label_id1的Label組件
rootview.setMapping({
"do_Button_6.text" : "node1.text_key",
"do_Button_7.text" : "node2",
"do_Button_6.bgColor" : "node1.color_key",
"do_Button_7.bgColor" : "node3"
});
// 建立Button和HashData的綁定
rootview.bindData(data);
// 數(shù)據(jù)變化驅(qū)動(dòng)UI屬性變化
// 1. 修改數(shù)據(jù)
data.addData({
"node1" : {
"text_key" : "多個(gè)子UI綁定1",
"color_key" : "1FFFE1BB"
},
"node2" : "多個(gè)子UI綁定2",
"node3" : "1111FFBB"
});
// 2. 刷新UI,二個(gè)按鈕的文本變成“多個(gè)子UI綁定1,2”推汽,背景顏色變?yōu)椤?F1F1EBB补疑,11111EBB"
rootview.refreshData();
}
2.特殊綁定方式:
這種bind機(jī)制不是所有UI組件都具有的,只有類似ListView歹撒,GridView等組件才有莲组,這種組件的共性在于用戶看到的視圖是有限的,但是實(shí)際上通過(guò)手勢(shì)滑動(dòng)可以有很多個(gè)數(shù)量不定的視圖暖夭。這種bind有以下幾個(gè)概念:
-
templates
:模板是這種類型組件的一個(gè)屬性,里面包含的是ui文件名锹杈。不管這種View有多少個(gè)子視圖,但是模板數(shù)量是固定的迈着,比如大部分ListView有很多個(gè)單元竭望,但是這些單元都是共用一個(gè)或幾個(gè)模板,只不過(guò)每一個(gè)單元對(duì)應(yīng)的數(shù)據(jù)不一樣裕菠。 -
bindItems
:這個(gè)是這種類型組件的一個(gè)方法咬清,這個(gè)方法的參數(shù)只能是do_ListData
,表明這個(gè)視圖和一個(gè)list數(shù)據(jù)結(jié)構(gòu)的數(shù)組對(duì)象綁定在一起。 -
refreshItems
:類似UI基類的refreshData方法奴潘,這個(gè)方法是這種類型組件的一個(gè)方法旧烧。當(dāng)bind的ListData發(fā)生變化后,通過(guò)這個(gè)方法來(lái)刷新界面画髓。
以下是一個(gè)ListView的示例代碼掘剪,這里面的代碼實(shí)際上是寫(xiě)在不同的2個(gè)ui文件對(duì)應(yīng)的ui.js文件里,比如ListView所在的文件叫listview_sample.ui.js
// listview_sample.ui.js文件
// 建立綁定.....
// 1. 根據(jù)ListView的ID獲取一個(gè)ListView的對(duì)象
var listview = ui("listview_id1");
// 2. 設(shè)置ListView的模板,這里只設(shè)置了一個(gè)模板文件雀扶,其實(shí)有可能有多個(gè)杖小。
//這個(gè)示例中,假設(shè)這個(gè)模板文件里面只有一個(gè)id為button_id1的Button組件
//在ui文件里設(shè)置listview的templates屬性為"source://listview_cell.ui"
//也可能支持多模板比如templates屬性為"source://listview_cell1.ui,source://listview_cell2.ui"
// 3. 創(chuàng)建一個(gè)ListData對(duì)象
var data = mm("do_ListData");
// 4. 建立ListView和ListData的綁定
listview.bindItems(data);
// 數(shù)據(jù)變化驅(qū)動(dòng)UI屬性變化
// 1. 修改數(shù)據(jù)
data.addData([{"text_key":"我是Button1","color_key":"#FFFFEEAA"},
{"text_key":"我是Button2","color_key":"#FFFFEEBB"},
{"text_key":"我是Button3","color_key":"#FFFFEECC"},
{"text_key":"我是Button4","color_key":"#FFFFEEDD"},
{"text_key":"我是Button5","color_key":"#FFFFEEEE"},
]);
// 2. 刷新UI,這個(gè)ListView會(huì)增加6個(gè)子視圖愚墓,每個(gè)視圖里的按鈕的文本變成“我是Button”+n,
//背景顏色變?yōu)椤癋FFFEE"+XX
listview.refreshItems();
以上的例子想要運(yùn)行成功昂勉,還需要在listview_cell.ui對(duì)應(yīng)的listview_cell.ui.js
文件里添加以下類似代碼
//listview_cell.ui.js文件
// 建立綁定.....
// 1. 根據(jù)統(tǒng)配符$來(lái)獲取ui文件的根節(jié)點(diǎn)浪册,也可以根據(jù)它的ID獲取對(duì)象
var rootview = ui("$");
// 2. 給rootview創(chuàng)建子UI的屬性到數(shù)據(jù)的映射,其中button_id1.text和button_id1.bgColor
//表示這個(gè)ui文件里有一個(gè)id為button_id1的Button組件
rootview.setMapping({"button_id1.text":"text_key","button_id1.bgColor":"color_key"});
//注意這里不需要再單獨(dú)bind一個(gè)數(shù)據(jù)源了,這個(gè)文件作為listview的模板文件岗照,會(huì)自動(dòng)和listview綁定的數(shù)據(jù)建立bind關(guān)系村象。
//listview綁定的數(shù)組數(shù)據(jù)中每一項(xiàng)元素都是這個(gè)模板文件的數(shù)據(jù)源笆环。
ListView用的很廣,示例也非常多厚者,參考示例大全
注意:當(dāng)組件綁定多個(gè)模板時(shí)躁劣,數(shù)據(jù)內(nèi)需要多加一個(gè)key為“template”,指定單條數(shù)據(jù)綁定的模板索引库菲,默認(rèn)從0開(kāi)始
3.dataRefreshed 事件:
這個(gè)事件也很重要账忘,通常一個(gè)UI對(duì)象和一個(gè)Hashdata建立映射關(guān)系之后,當(dāng)hashdata更新數(shù)據(jù)后熙宇,UI對(duì)象調(diào)用refreshData或refreshItems后鳖擒,UI對(duì)象會(huì)接受到數(shù)據(jù),然后更新對(duì)應(yīng)的屬性值烫止,之后會(huì)觸發(fā)這個(gè)事件蒋荚。
這個(gè)事件會(huì)通常可以用在Listview馆蠕,Gridview期升,Slideview這種UI組件,它們都包含多個(gè)ui文件互躬,都有模板ui文件吓妆。通過(guò)這個(gè)事件可以實(shí)現(xiàn)主ui和模板ui的數(shù)據(jù)通訊。