天天看點

深入學習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”.

深入學習SAP UI5架構代碼系列之五:SAP UI5控件的執行個體資料修改和讀取邏輯
深入學習SAP UI5架構代碼系列之五:SAP UI5控件的執行個體資料修改和讀取邏輯

點了三次按鈕後,其渲染出的HTML代碼如下圖所示,button的text屬性後面多了三個"1":

深入學習SAP UI5架構代碼系列之五:SAP UI5控件的執行個體資料修改和讀取邏輯

單步調試進入setText方法内部,發現該方法最終執行的實作是ManagedObject.setProperty:

深入學習SAP UI5架構代碼系列之五:SAP UI5控件的執行個體資料修改和讀取邏輯

我們可以通過上圖右邊調用棧裡實作,複習本系列之前文章學到的兩個知識點:

(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的代碼本身的執行邏輯也很清晰。

深入學習SAP UI5架構代碼系列之五:SAP UI5控件的執行個體資料修改和讀取邏輯

第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架構代碼系列之五:SAP UI5控件的執行個體資料修改和讀取邏輯

每個不同類型的SAP UI5控件屬性,根據其中繼資料的type字段,可以得到一個對應的類型描述器,如上圖1409行oType所示。

描述器裡包含一系列方法,其中normalize函數負責在寫入新的屬性值時,對輸入值進行規則化處理。

深入學習SAP UI5架構代碼系列之五:SAP UI5控件的執行個體資料修改和讀取邏輯

在setProperty調用時,最後一個可選的輸入參數bSuppressInvalidate,預設值為undefined,是以會執行1316行的invalidate方法,觸發UI的重繪操作(rerendering)。

深入學習SAP UI5架構代碼系列之五:SAP UI5控件的執行個體資料修改和讀取邏輯

上圖第1313行隻是将新的屬性值寫入SAP UI5控件的執行個體資料存儲結構裡,該行代碼執行完畢後,UI上的button标簽文本并不會變化。

隻有當UI界面重繪完成後,使用者才能在浏覽器裡看到button标簽的最新值。

上圖1316行的invalidate方法,會以異步的方式觸發UI重繪操作。異步操作的排程,采用JavaScript原生函數setTimeout, 該函數将renderPendingUIUpdates這個任務添加到JavaScript引擎任務隊列的尾部,這樣主線程一旦空閑(因為setTimeout第二個參數,即逾時時間指定為0),就會執行renderPendingUIUpdates,以重繪UI區域裡需要重繪,即屬性值發生了變化的那些控件。

深入學習SAP UI5架構代碼系列之五:SAP UI5控件的執行個體資料修改和讀取邏輯

Button控件的重繪,最終通過其對應的渲染器,ButtonRenderer來實作,具體的渲染方法render的調用,如上圖右部标注了數字4的調用棧棧幀所示。

關于SAP UI5控件的渲染器,請檢視Jerry之前的文章 深入學習SAP UI5架構代碼系列之二:UI5 控件的渲染器。

再回到ManagedObject.setProperty的方法主體。

1320行的this.updateModelProperty, 涉及到SAP UI5控件對應的模型更新,在代碼1319行注釋裡提到,如果控件使用雙向綁定方式同一個模型綁定,那麼當UI控件屬性發生變化時,對應的模型字段也應該被更新。這個模型字段的更新就實作在1320行的updateModelProperty函數裡,Jerry的下一篇文章 UI5控件資料綁定的實作原理 會介紹。

深入學習SAP UI5架構代碼系列之五:SAP UI5控件的執行個體資料修改和讀取邏輯

ManagedObject.setProperty的末尾,會調用實作在原型鍊節點EventProvider上的fireEvent方法,抛出一個_change事件,包含發生該事件的控件id,發生change的屬性名稱,變化前和變化後的屬性值。

深入學習SAP UI5架構代碼系列之五:SAP UI5控件的執行個體資料修改和讀取邏輯

雖然事件名稱_change前面的下劃線表明該事件用于SAP UI5架構内部處理,然而這隻是一個弱限制,我們依舊可以在自己的應用程式裡,使用下圖高亮區域裡button控件的attachEvent方法,來監聽這個事件。

下圖右部分調試器Watch面闆裡展示的是_change事件的負載,表明一個id為__button0的控件,text屬性值從Jerry變成了Jerry1.

深入學習SAP UI5架構代碼系列之五:SAP UI5控件的執行個體資料修改和讀取邏輯

以上就是button控件的setText->setProperty的執行邏輯的大緻介紹,了解了SAP UI5控件資料修改的原理,了解getText就容易多了。

前面介紹setProperty的時候提到了執行UI重繪的異步操作,發生在renderPendingUIUpdates函數裡,這裡button控件的渲染器ButtonRenderer的render方法會被調用。渲染器又調用button的getText方法,取出待渲染的button标簽值。

深入學習SAP UI5架構代碼系列之五:SAP UI5控件的執行個體資料修改和讀取邏輯

而getText同setText類似,轉而調用ManagedObject的getProperty方法:

深入學習SAP UI5架構代碼系列之五:SAP UI5控件的執行個體資料修改和讀取邏輯

getProperty的核心邏輯比setProperty簡單得多,直接從控件執行個體資料存儲結構mProperties裡取出對應需要讀取的屬性值。

深入學習SAP UI5架構代碼系列之五:SAP UI5控件的執行個體資料修改和讀取邏輯

順便說一句,Angular同SAP UI5一樣,也有類似的UI異步重繪操作。

每當Angular内部維護的微任務隊列為空時,(onMicrotaskEmpty), 觸發tick操作:

深入學習SAP UI5架構代碼系列之五:SAP UI5控件的執行個體資料修改和讀取邏輯

tick操作調用detectChanges函數(相當于SAP UI5的renderPendingUIUpdates), detectChanges會遞歸調用refreshView, 重新整理發生了屬性變化的Angular控件。

深入學習SAP UI5架構代碼系列之五:SAP UI5控件的執行個體資料修改和讀取邏輯

本系列的下一篇文章,會介紹SAP UI5控件資料綁定的實作原理,感謝閱讀。

繼續閱讀