數據綁定是在應用程式 UI 與數據源建立連接的過程。如果綁定正確數據,則當數據更改其值時,綁定到數據的UI屬性值會自動反映更改。DeviceOne支持靈活的數據綁定,使UI展示和數據可以清晰的分離。目前還不支持雙向綁定,只支持數據到展示的傳遞。使用DeviceOne開發App,你可以不使用任何數據b ...
數據綁定是在應用程式 UI 與數據源建立連接的過程。如果綁定正確數據,則當數據更改其值時,綁定到數據的UI屬性值會自動反映更改。DeviceOne支持靈活的數據綁定,使UI展示和數據可以清晰的分離。目前還不支持雙向綁定,只支持數據到展示的傳遞。
使用DeviceOne開發App,你可以不使用任何數據bind機制,傳統的獲取對象,給對象每一個單個屬性設置值也可以實現所有功能。但是使用bind機制可以減少代碼,優化框架,使開發工作事半功倍。
1.基本綁定方式:
bind包括源和目標,DeviceOne的bind目標通常指UI組件,所有的UI組件都支持基本的bind方式。實際上只要一個組件有屬性就可以支持bind,比如UI和MM(MultitonModule)組件都有屬性,都支持bind。
bind的源我們目前提供了2個組件do_ListData
和do_HashData
分別表示二種數據結構,hash和array,因為整個DeviceOne的數據基礎都是json格式,所以這2個數據組件都是只能處理json格式。
UI和MM類的基類都提供了3個相關的方法來實現bind機制。
setMapping
方法:設置一個UI組件或者MM組件的屬性和數據的映射關係。bindData
方法:設置UI組件或者MM組件的數據源,這個數據源目前只能是do_ListData
和do_HashData
.refreshData
方法:當bind的數據源數據發生變化後,調用這個方法來刷新數據源的展示。
1 function test1() { 2 // 創建一個HashData對象 3 var data = mm("do_HashData"); 4 // 給Button創建一個屬性到數據的映射,其中text和bgColor是Button的2個屬性 5 btn1.setMapping({ 6 "text" : "text_key", 7 "bgColor" : "color_key" 8 }); 9 // 建立Button和HashData的綁定 10 btn1.bindData(data); 11 // 數據變化驅動UI屬性變化 12 // 1. 修改數據 13 data.addData({ 14 "text_key" : "映射到HashData", 15 "color_key" : "FF0022AA" 16 }); 17 // 2. 刷新UI,這個按鈕的文本變成“映射到HashData”,背景顏色變為“FF0022AA" 18 btn1.refreshData(); 19 }
其中一個UI的映射可以作為bindData的一個參數,比如
1 function test2() { 2 // 創建一個HashData對象 3 var data = mm("do_HashData"); 4 // 建立Button和HashData的綁定,同時設置映射關係 5 btn2.bindData(data, { 6 "text" : "text_key", 7 "bgColor" : "color_key" 8 }); 9 // 數據變化驅動UI屬性變化 10 // 1. 修改數據 11 data.addData({ 12 "text_key" : "映射到HashData-直接設置映射", 13 "color_key" : "FFCC00AA" 14 }); 15 // 2. 刷新UI,這個按鈕的文本變成“映射到HashData-直接設置映射”,背景顏色變為“FFCC00AA" 16 btn2.refreshData(); 17 } 18 // ...
其中HashData對象支持path,中間用.號來隔開,比如
function test3() { // 創建一個HashData對象 var data = mm("do_HashData"); // 給Button創建一個屬性到數據的映射,其中text和bgColor是Button的2個屬性 // HashData對象支持path,中間用.號來隔開 btn3.setMapping({ "text" : "node1.text_key", "bgColor" : "node1.color_key" }); // 建立Button和HashData的綁定 btn3.bindData(data); // 數據變化驅動UI屬性變化 // 1. 修改數據 data.addData({ "node1" : { "text_key" : "映射到HashData-支持path", "color_key" : "F00FEEAA" }, "node2" : "xxxx" }); // 2. 刷新UI,這個按鈕的文本變成“映射到HashData-支持path”,背景顏色變為“F00FEEAA" btn3.refreshData(); }
其中數據源也支持ListData,中間用:加數字索引來表明是一個list的一個元素
function test4() { // 創建一個HashData對象 var data = mm("do_HashData"); // 給Button創建一個屬性到數據的映射,其中text和bgColor是Button的2個屬性 // HashData對象支持json array,中間用:加數字索引來表明是一個array的一個元素 btn4.setMapping({ "text" : "node1:2.text_key", "bgColor" : "node1:2.color_key" }); // 建立Button和HashData的綁定 btn4.bindData(data); // 數據變化驅動UI屬性變化 // 1. 修改數據 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,這個按鈕的文本變成“映射到HashData-支持JSONArray”,背景顏色變為“00FFEECC" btn4.refreshData(); } function test5() { // 創建一個ListData對象 var data = mm("do_ListData"); // 給Button創建一個屬性到數據的映射,其中text和bgColor是Button的2個屬性 // do_ListData對象支持:加數字索引來表明是一個array的一個元素 btn5.setMapping({ "text" : ":2.text_key", "bgColor" : ":2.color_key" }); // 建立Button和HashData的綁定 btn5.bindData(data); // 數據變化驅動UI屬性變化 // 1. 修改數據 data.addData([ { "text_key" : "我是Button1", "color_key" : "FFFFEEAA" }, { "text_key" : "我是Button2", "color_key" : "FFFFEEBB" }, { "text_key" : "映射到ListData", "color_key" : "0FF11ECC" } ]); // 2. 刷新UI,這個按鈕的文本變成“映射到HashData-支持JSONArray”,背景顏色變為“00F11ECC" btn5.refreshData(); }
其中bind目標UI也支持path,中間用.隔開,只不過有一個限制就是這個時候的綁定目標UI必須是這個ui文件的根節點。這種情況應用更靈活方便,不需要為每一個UI創建一個映射和一個數據源,這個ui文件里所有UI組件可以共用一個映射和數據源。比如
function test6() { // 根據統配符$來獲取ui文件的根節點,也可以根據它的ID獲取對象 var rootview = ui("$"); // 創建一個HashData對象 var data = mm("do_HashData"); // 給rootview創建多個子UI的屬性到數據的映射,其中button_id1.text和label_id1.text // 分別表示這個ui文件里一個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); // 數據變化驅動UI屬性變化 // 1. 修改數據 data.addData({ "node1" : { "text_key" : "多個子UI綁定1", "color_key" : "1FFFE1BB" }, "node2" : "多個子UI綁定2", "node3" : "1111FFBB" }); // 2. 刷新UI,二個按鈕的文本變成“多個子UI綁定1,2”,背景顏色變為“1F1F1EBB,11111EBB" rootview.refreshData(); }
2. 特殊綁定方式:
這種bind機制不是所有UI組件都具有的,只有類似ListView,GridView等組件才有,這種組件的共性在於用戶看到的視圖是有限的,但是實際上通過手勢滑動可以有很多個數量不定的視圖。這種bind有以下幾個概念:
templates
:模板是這種類型組件的一個屬性,裡面包含的是ui文件名。不管這種View有多少個子視圖,但是模板數量是固定的,比如大部分ListView有很多個單元,但是這些單元都是共用一個或幾個模板,只不過每一個單元對應的數據不一樣。bindItems
:這個是這種類型組件的一個方法,這個方法的參數只能是do_ListData
,表明這個視圖和一個list數據結構的數組對象綁定在一起。refreshItems
:類似UI基類的refreshData方法,這個方法是這種類型組件的一個方法。當bind的ListData發生變化後,通過這個方法來刷新界面。
以下是一個ListView的示例代碼,這裡面的代碼實際上是寫在不同的2個ui文件對應的ui.js文件里,比如ListView所在的文件叫listview_sample.ui.js
// listview_sample.ui.js文件 // 建立綁定..... // 1. 根據ListView的ID獲取一個ListView的對象 var listview = ui("listview_id1"); // 2. 設置ListView的模板,這裡只設置了一個模板文件,其實有可能有多個。 //這個示例中,假設這個模板文件裡面只有一個id為button_id1的Button組件 //在ui文件里設置listview的templates屬性為"source://listview_cell.ui" //也可能支持多模板比如templates屬性為"source://listview_cell1.ui,source://listview_cell2.ui" // 3. 創建一個ListData對象 var data = mm("do_ListData"); // 4. 建立ListView和ListData的綁定 listview.bindItems(data); // 數據變化驅動UI屬性變化 // 1. 修改數據 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,這個ListView會增加6個子視圖,每個視圖裡的按鈕的文本變成“我是Button”+n, //背景顏色變為“FFFFEE"+XX listview.refreshItems();
以上的例子想要運行成功,還需要在listview_cell.ui對應的listview_cell.ui.js
文件里添加以下類似代碼
1 //listview_cell.ui.js文件 2 // 建立綁定..... 3 // 1. 根據統配符$來獲取ui文件的根節點,也可以根據它的ID獲取對象 4 var rootview = ui($); 5 // 2. 給rootview創建子UI的屬性到數據的映射,其中button_id1.text和button_id1.bgColor 6 //表示這個ui文件里有一個id為button_id1的Button組件 7 rootview.setMapping({"button_id1.text":"text_key","button_id1.bgColor":"color_key"}); 8 //註意這裡不需要再單獨bind一個數據源了,這個文件作為listview的模板文件,會自動和listview綁定的數據建立bind關係。 9 //listview綁定的數組數據中每一項元素都是這個模板文件的數據源。
ListView用的很廣,示例也非常多,參考示例大全
3. dataRefreshed 事件:
這個事件也很重要,通常一個UI對象和一個Hashdata建立映射關係之後,當hashdata更新數據後,UI對象調用refreshData或refreshItems後,UI對象會接受到數據,然後更新對應的屬性值,之後會觸發這個事件。
這個事件會通常可以用在Listview,Gridview,Slideview這種UI組件,它們都包含多個ui文件,都有模板ui文件。通過這個事件可以實現主ui和模板ui的數據通訊。
詳細的示例我們參考數據傳遞的文檔