深入学习SAP UI5框架代码系列之五:SAP UI5控件的实例数据修改和读取逻辑
這是Jerry 2021年的第6篇文章,也是汪子熙公眾號總共第277篇原創文章。
系列目錄
(0)?SAP UI5應用開發人員了解UI5框架代碼的意義
(1)?SAP UI5 module懶加載機制
(2)?SAP UI5 控件渲染機制
(3)?HTML原生事件 VS SAP UI5 Semantic事件
(4)?SAP UI5控件元數據的元數據實現
(5) SAP UI5控件的實例數據修改和讀取邏輯(本文)
(6) SAP UI5控件數據綁定的實現原理
(7) SAP UI5控件數據綁定的三種模式:One Way,Two Way和OneTime實現原理比較
(8) SAP UI5控件ID的生成邏輯
(9) SAP UI5控件的多語言(國際化,Internationalization,i18n)支持的實現原理
(10) XML視圖里的button控件
(11) button控件和它背后的DOM元素
本文我們將通過研究button控件的setText和getText方法實現,來學習SAP UI5控件的實例數據修改和讀取邏輯。
下圖是一段簡單的SAP UI5代碼:每點擊一次button,就會在press事件的響應函數里,給button的text屬性值尾部附上一個字符“1”.
點了三次按鈕后,其渲染出的HTML代碼如下圖所示,button的text屬性后面多了三個"1":
單步調試進入setText方法內部,發現該方法最終執行的實現是ManagedObject.setProperty:
我們可以通過上圖右邊調用棧里實現,復習本系列之前文章學到的兩個知識點:
(1) 文章?深入學習SAP UI5框架代碼系列之一:UI5 Module的懶加載機制?里提到的SAP UI5控件的原型繼承鏈:
Button->Control->Element->ManagedObject->EventProvider->BaseObject
(2) 文章?HTML原生事件 VS SAP UI5 Semantic事件?里提到的從HTML原生的click事件到SAP UI5 press語義事件的映射邏輯。
setProperty的實現邏輯概述
注釋寫得很棒,不過setProperty的代碼本身的執行邏輯也很清晰。
第1295行this.mProperties即SAP UI5控件的實例數據存儲結構。上圖右上角Watch面板里的含義是,當前setProperty方法調用,需要修改text屬性,修改成新的值為"Button1".
1295行首先從this.mProperties中取出text屬性修改前的值,存儲在變量oOldValue里。
1298行調用this.validateProperty方法,檢查傳入setProperty的輸入參數,即待修改的屬性值oValue是否有效。
1300行判斷修改前的值oOldValue,和待修改的輸入值oValue是否相同。如果相同,當前setProperty調用沒必要繼續執行,直接返回。
在validateProperty內部,SAP UI5框架根據本系列前一篇文章?深入學習SAP UI5框架代碼系列之四:SAP UI5控件的元數據實現?描述的邏輯, 取出控件text屬性的元數據,得知該屬性類型為string,訪問權限為public:
每個不同類型的SAP UI5控件屬性,根據其元數據的type字段,可以得到一個對應的類型描述器,如上圖1409行oType所示。
描述器里包含一系列方法,其中normalize函數負責在寫入新的屬性值時,對輸入值進行規則化處理。
在setProperty調用時,最后一個可選的輸入參數bSuppressInvalidate,默認值為undefined,因此會執行1316行的invalidate方法,觸發UI的重繪操作(rerendering)。
上圖第1313行只是將新的屬性值寫入SAP UI5控件的實例數據存儲結構里,該行代碼執行完畢后,UI上的button標簽文本并不會變化。
只有當UI界面重繪完成后,用戶才能在瀏覽器里看到button標簽的最新值。
上圖1316行的invalidate方法,會以異步的方式觸發UI重繪操作。異步操作的調度,采用JavaScript原生函數setTimeout, 該函數將renderPendingUIUpdates這個任務添加到JavaScript引擎任務隊列的尾部,這樣主線程一旦空閑(因為setTimeout第二個參數,即超時時間指定為0),就會執行renderPendingUIUpdates,以重繪UI區域里需要重繪,即屬性值發生了變化的那些控件。
Button控件的重繪,最終通過其對應的渲染器,ButtonRenderer來實現,具體的渲染方法render的調用,如上圖右部標注了數字4的調用棧棧幀所示。
關于SAP UI5控件的渲染器,請查看Jerry之前的文章?深入學習SAP UI5框架代碼系列之二:UI5 控件的渲染器。
再回到ManagedObject.setProperty的方法主體。
1320行的this.updateModelProperty, 涉及到SAP UI5控件對應的模型更新,在代碼1319行注釋里提到,如果控件使用雙向綁定方式同一個模型綁定,那么當UI控件屬性發生變化時,對應的模型字段也應該被更新。這個模型字段的更新就實現在1320行的updateModelProperty函數里,Jerry的下一篇文章 UI5控件數據綁定的實現原理 會介紹。
ManagedObject.setProperty的末尾,會調用實現在原型鏈節點EventProvider上的fireEvent方法,拋出一個_change事件,包含發生該事件的控件id,發生change的屬性名稱,變化前和變化后的屬性值。
雖然事件名稱_change前面的下劃線表明該事件用于SAP UI5框架內部處理,然而這只是一個弱約束,我們依舊可以在自己的應用程序里,使用下圖高亮區域里button控件的attachEvent方法,來監聽這個事件。
下圖右部分調試器Watch面板里展示的是_change事件的負載,表明一個id為__button0的控件,text屬性值從Jerry變成了Jerry1.
以上就是button控件的setText->setProperty的執行邏輯的大致介紹,了解了SAP UI5控件數據修改的原理,理解getText就容易多了。
前面介紹setProperty的時候提到了執行UI重繪的異步操作,發生在renderPendingUIUpdates函數里,這里button控件的渲染器ButtonRenderer的render方法會被調用。渲染器又調用button的getText方法,取出待渲染的button標簽值。
而getText同setText類似,轉而調用ManagedObject的getProperty方法:
getProperty的核心邏輯比setProperty簡單得多,直接從控件實例數據存儲結構mProperties里取出對應需要讀取的屬性值。
順便說一句,Angular同SAP UI5一樣,也有類似的UI異步重繪操作。
每當Angular內部維護的微任務隊列為空時,(onMicrotaskEmpty), 觸發tick操作:
tick操作調用detectChanges函數(相當于SAP UI5的renderPendingUIUpdates), detectChanges會遞歸調用refreshView, 刷新發生了屬性變化的Angular控件。
本系列的下一篇文章,會介紹SAP UI5控件數據綁定的實現原理,感謝閱讀。
系列目錄
(0)?SAP UI5應用開發人員了解UI5框架代碼的意義
(1)?SAP UI5 module懶加載機制
(2)?SAP UI5 控件渲染機制
(3)?HTML原生事件 VS SAP UI5 Semantic事件
(4)?SAP UI5控件元數據的元數據實現
(5) SAP UI5控件的實例數據修改和讀取邏輯(本文)
(6) SAP UI5控件數據綁定的實現原理
(7) SAP UI5控件數據綁定的三種模式:One Way,Two Way和OneTime實現原理比較
(8) SAP UI5控件ID的生成邏輯
(9) SAP UI5控件的多語言(國際化,Internationalization,i18n)支持的實現原理
(10) XML視圖里的button控件
(11) button控件和它背后的DOM元素
更多Jerry的原創文章,盡在:“汪子熙”:
總結
以上是生活随笔為你收集整理的深入学习SAP UI5框架代码系列之五:SAP UI5控件的实例数据修改和读取逻辑的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: TypeScript里数组foreach
- 下一篇: 迷你世界并不会永久下架!