深入学习SAP UI5框架代码系列之六:SAP UI5控件数据绑定的实现原理
這是Jerry 2021年的第 7 篇文章,也是汪子熙公眾號(hào)總共第 278 篇原創(chuàng)文章。
系列目錄
(0)?SAP UI5應(yīng)用開(kāi)發(fā)人員了解UI5框架代碼的意義
(1)?SAP UI5 module懶加載機(jī)制
(2)?SAP UI5 控件渲染機(jī)制
(3)?HTML原生事件 VS SAP UI5 Semantic事件
(4)?SAP UI5控件元數(shù)據(jù)的元數(shù)據(jù)實(shí)現(xiàn)
(5)?SAP UI5控件的實(shí)例數(shù)據(jù)修改和讀取邏輯
(6) SAP UI5控件數(shù)據(jù)綁定的實(shí)現(xiàn)原理(本文)
(7) SAP UI5控件數(shù)據(jù)綁定的三種模式:One Way,Two Way和OneTime實(shí)現(xiàn)原理比較
(8) SAP UI5控件ID的生成邏輯
(9) SAP UI5控件的多語(yǔ)言(國(guó)際化,Internationalization,i18n)支持的實(shí)現(xiàn)原理
(10) XML視圖里的button控件
(11) button控件和它背后的DOM元素
Jerry使用Angular做開(kāi)發(fā)已經(jīng)有幾個(gè)月了,其間也學(xué)習(xí)了Angular控件的數(shù)據(jù)綁定,再回過(guò)頭來(lái)重溫SAP UI5控件數(shù)據(jù)綁定,別有一番味道。
之前Jerry時(shí)不時(shí)會(huì)在微信上收到一些朋友的咨詢,諸如:“我的SAP UI5控件做了綁定,從Chrome開(kāi)發(fā)者工具也能看到后臺(tái)返回的OData API確實(shí)包含了數(shù)據(jù),但是UI5頁(yè)面渲染出來(lái)之后,為什么控件上沒(méi)有顯示綁定的數(shù)據(jù)呢?”此類問(wèn)題。
其實(shí),如果了解一些SAP UI5控件的數(shù)據(jù)綁定實(shí)現(xiàn)細(xì)節(jié),此類問(wèn)題完全可以通過(guò)自己調(diào)試的方式去排錯(cuò)。
我們還是使用之前文章 一個(gè)用于SAP UI5學(xué)習(xí)的腳手架應(yīng)用,沒(méi)有任何后臺(tái)API的依賴 提到的腳手架應(yīng)用來(lái)學(xué)習(xí)。
添加下列五行高亮代碼:
創(chuàng)建一個(gè)新的JSON模型,包含一個(gè)字段field_for_text, 值為Jerry,再將該模型綁定到button控件,模型字段field_for_text綁定到button的text屬性。
這樣一來(lái),運(yùn)行時(shí)看到按鈕的標(biāo)簽就成了field_for_text的值"Jerry",而不是第18行給text屬性賦予的硬編碼值"Button":
本文的目的就是,闡述清楚第一張圖高亮的五行代碼,背后發(fā)生了什么事情。
var oModel = new sap.ui.model.json.JSONModel();
當(dāng)這行代碼執(zhí)行之后,JSONModel以及包含對(duì)應(yīng)的模型綁定實(shí)現(xiàn)邏輯的JavaScript源文件會(huì)自動(dòng)被加載,這體現(xiàn)了SAP UI5 Module的懶加載特性,在本系列這篇文章里介紹過(guò):深入學(xué)習(xí)SAP UI5框架代碼系列之一:UI5 Module的懶加載機(jī)制。
本系列之前的文章,我們?cè)?jīng)多次提及SAP UI5控件的原型繼承鏈:
Button -> Control -> Element -> ManagedObject
-> EventProvider -> BaseObject
本文我們會(huì)學(xué)習(xí)到另一條原型繼承鏈:
JSONModel -> ClientModel -> Model -> MessageProcessor -> EventProvider -> BaseObject
從上圖第61行的構(gòu)造函數(shù)的輸入?yún)?shù)oData,不難發(fā)現(xiàn),在UI5應(yīng)用里創(chuàng)建JSONModel實(shí)例時(shí),可以將模型存儲(chǔ)的數(shù)據(jù)一并指定。
這樣,我們之前腳手架應(yīng)用里的代碼,可以精簡(jiǎn)成下圖右邊所示:
單步調(diào)試JSONModel的構(gòu)造函數(shù),會(huì)發(fā)現(xiàn)它依次會(huì)調(diào)用原型繼承鏈上游節(jié)點(diǎn)的ClientModel,Model和MessageProcessor的構(gòu)造函數(shù)。
下圖是Model構(gòu)造函數(shù)的實(shí)現(xiàn),信息量很大:
(1) 第69行,說(shuō)明SAP UI5模型綁定的默認(rèn)方式是雙向綁定;
(2) 第83行,說(shuō)明SAP UI5模型綁定支持單向,雙向和單次綁定。本系列下一篇文章 SAP UI5控件數(shù)據(jù)綁定的三種模式:One Way,Two Way和OneTime實(shí)現(xiàn)原理比較 會(huì)介紹這三種方式的區(qū)別。
oModel.setData(myData);
將一個(gè)JSON對(duì)象通過(guò)setData傳入JSONModel實(shí)例。
setData方法有一個(gè)可選參數(shù)bMerge,如果顯式指定為true,則會(huì)調(diào)用下圖88行的jQuery.extend, 將本地傳入的JSON對(duì)象同JSONModel原有的數(shù)據(jù)進(jìn)行合并(merge). 因?yàn)槲覀儽纠{(diào)用setData并未指定該參數(shù),所以不進(jìn)行合并,直接執(zhí)行95行的checkUpdate:
因?yàn)榇藭r(shí)UI5 button控件實(shí)例尚未同JSONModel實(shí)例建立綁定關(guān)系,所以模型的aBindings數(shù)組為空,因此checkUpdate實(shí)際并未執(zhí)行任何和控件綁定相關(guān)的操作,直接返回。
oButton1.setModel(oModel);
這行語(yǔ)句的作用,就是將控件實(shí)例和傳入方法的JSONModel實(shí)例建立綁定關(guān)系。
- 4597~4604:該IF分支處理UI5控件之前已經(jīng)綁定到某個(gè)模型實(shí)例的情況,此時(shí)使用delete操作,刪除原有的模型引用,然后更新綁定信息。而本例是button控件第一次調(diào)用setModel,故不會(huì)進(jìn)入此IF分支。
- 4607:UI5控件維護(hù)了一個(gè)類似字典的鍵值對(duì)數(shù)據(jù)結(jié)構(gòu),key為模型名稱,value為模型實(shí)例。從此處的SAP UI5源代碼實(shí)現(xiàn)不難得出結(jié)論,UI5控件支持同時(shí)綁定到多個(gè)模型實(shí)例上,只要該控件在調(diào)用setModel方法時(shí),給傳入的模型實(shí)例通過(guò)方法第二個(gè)參數(shù)sName,賦予不同的模型名稱即可。
至此,JSONModel實(shí)例的field_for_text字段值,還不會(huì)自動(dòng)流向button控件的text屬性,直到下面這行代碼的執(zhí)行。
oButton1.bindProperty(“text”, “/field_for_text”);
該方法首先構(gòu)造了一個(gè)包含JSONModel綁定字段的對(duì)象oBindingInfo:
將該oBindingInfo維護(hù)到控件的中央綁定信息存儲(chǔ)數(shù)據(jù)結(jié)構(gòu)mBindingInfos里,該數(shù)據(jù)結(jié)構(gòu)同樣是一個(gè)鍵值對(duì),key為控件屬性,本例為text,值為oBindingInfo對(duì)象,對(duì)象里包含了text屬性綁定到JSONModel實(shí)例的字段名稱:field_for_text.
單步調(diào)試進(jìn)入上圖3347行的_bindProperty方法:
3417行,調(diào)用JSONModel的bindProperty方法,生成oBinding對(duì)象:
這里再次出現(xiàn)了關(guān)于SAP UI5數(shù)據(jù)綁定的三種模式處理的源代碼,本系列后續(xù)文章會(huì)專門介紹。
3433行將生成的oBinding對(duì)象實(shí)例,添加到aBindings數(shù)組里。
那么oBinding實(shí)例是如何生成的?需要單步調(diào)試上圖3417行的oModel.bindProperty代碼。
JSONModel.bindProperty的實(shí)現(xiàn),就是一個(gè)單純的new調(diào)用。不過(guò)更重要的是,此處我們了解到了另一條原型繼承鏈:
JSONPropertyBinding -> ClientPropertyBinding -> PropertyBinding -> Binding -> EventProvider -> BaseObject
我們注意到,在oBinding實(shí)例里,有個(gè)字段叫做oValue, 其值正好是JSONModel實(shí)例維護(hù)的JSON對(duì)象字段field_for_text的值Jerry. 實(shí)際上,最后button控件的text屬性,顯示的值正是oBinding實(shí)例oValue字段的值。
所以需要搞清楚this.oValue的賦值邏輯,就得單步執(zhí)行上圖第35行的this._getValue方法。
this._getValue()
該函數(shù)負(fù)責(zé)將field_for_text字段的值,從this.oModel.oData.field_for_text字段中提取出來(lái),如下圖所示:
一旦this._getValue執(zhí)行完之后,控件text屬性同JSONModel實(shí)例的field_for_text字段就成功建立起綁定關(guān)系,之后我們就能直接從控件實(shí)例變量oButton1出發(fā),去找到其text屬性應(yīng)該顯示的值:
希望通過(guò)本文的介紹,能讓大家對(duì)SAP UI5控件數(shù)據(jù)綁定的實(shí)現(xiàn)原理有一個(gè)最基本的了解。
如果遇到控件綁定不能按照自己的期望工作的時(shí)候,不妨試試按照本文提到的這些關(guān)鍵點(diǎn)去調(diào)試。
本系列下一篇文章,會(huì)介紹SAP UI5控件數(shù)據(jù)綁定的三種模式:One Way,Two Way和OneTime的實(shí)現(xiàn)原理比較。
我的實(shí)際工作中發(fā)現(xiàn),了解了SAP UI5這些數(shù)據(jù)綁定方式的實(shí)現(xiàn),對(duì)我近期學(xué)習(xí)Angular的數(shù)據(jù)綁定也有一定的借鑒作用。
感謝閱讀。
系列目錄
(0)?SAP UI5應(yīng)用開(kāi)發(fā)人員了解UI5框架代碼的意義
(1)?SAP UI5 module懶加載機(jī)制
(2)?SAP UI5 控件渲染機(jī)制
(3)?HTML原生事件 VS SAP UI5 Semantic事件
(4)?SAP UI5控件元數(shù)據(jù)的元數(shù)據(jù)實(shí)現(xiàn)
(5)?SAP UI5控件的實(shí)例數(shù)據(jù)修改和讀取邏輯
(6) SAP UI5控件數(shù)據(jù)綁定的實(shí)現(xiàn)原理(本文)
(7) SAP UI5控件數(shù)據(jù)綁定的三種模式:One Way,Two Way和OneTime實(shí)現(xiàn)原理比較
(8) SAP UI5控件ID的生成邏輯
(9) SAP UI5控件的多語(yǔ)言(國(guó)際化,Internationalization,i18n)支持的實(shí)現(xiàn)原理
(10) XML視圖里的button控件
(11) button控件和它背后的DOM元素
更多Jerry的原創(chuàng)文章,盡在:“汪子熙”:
總結(jié)
以上是生活随笔為你收集整理的深入学习SAP UI5框架代码系列之六:SAP UI5控件数据绑定的实现原理的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: SAP Spartacus user f
- 下一篇: SAP Spartacus的persis