天天看點

深入學習SAP UI5架構代碼系列之一:UI5 Module的懶加載機制

本文是深入學習SAP UI5架構代碼系列的第二篇文章。

系列目錄

SAP UI5應用開發人員了解UI5架構代碼的意義

UI5 module懶加載機制

UI5 控件渲染機制

HTML原生事件 VS SAP UI5 Semantic事件

UI5控件中繼資料實作細節

UI5控件的執行個體資料實作細節

UI5控件資料綁定的實作原理

UI5控件資料綁定的三種模式:One Way,Two Way和OneTime實作原理比較

UI5控件ID的生成邏輯

UI5控件的多語言(國際化,Internationalization,i18n)支援的實作原理

XML視圖裡的button控件

button控件和它背後的DOM元素

通過Jerry前一篇文章 一個用于SAP UI5學習的腳手架應用,沒有任何背景API的依賴 介紹的腳手架應用,建立一個隻包含一個Button控件的UI5應用:

深入學習SAP UI5架構代碼系列之一:UI5 Module的懶加載機制

浏覽器裡打開,總共觸發了18個請求,網絡傳輸流量1.1MB, 頁面總共加載了5.1MB資源(見下圖底部紫色矩形框所示)。

深入學習SAP UI5架構代碼系列之一:UI5 Module的懶加載機制

順便說一說,為什麼頁面加載的資源尺寸(5.1 MB)會大于網絡傳輸的資料量(1.1 MB)?

網上有一種說法,頁面加載的資源,是通過網絡加載的資源,以及從浏覽器緩存讀取的資源總和,是以會出現Chrome開發者工具裡顯示的頁面加載的資源尺寸大于網絡傳輸資料量的情況。

這種說法不完全正确。更準确的說,頁面加載資源統計的是前端頁面加載的所有資源,經過解壓之後的原始大小。

如圖,打開Chrome開發者工具的Use Large request rows選項, 就能顯示出經過網絡加載資源解壓縮過後的原始大小,如下圖所示:

深入學習SAP UI5架構代碼系列之一:UI5 Module的懶加載機制

以上說明來自Google官網:

https://developers.google.com/web/tools/chrome-devtools/network/reference#uncompressed

回到我們的UI5應用,Ctrl+Alt+Shift+P,選中"Use Debu Sources",讓SAP UI5加載調試版本的庫檔案:

深入學習SAP UI5架構代碼系列之一:UI5 Module的懶加載機制
深入學習SAP UI5架構代碼系列之一:UI5 Module的懶加載機制

回憶一下我們的腳手架應用的代碼裡,建立了一個命名空間sap.ui.commons下的Button控件執行個體:

深入學習SAP UI5架構代碼系列之一:UI5 Module的懶加載機制

是以運作時,SAP UI5對應的Button Module會被加載。Button-dbg.js負責Button的生命周期管理和事件響應,ButtonRenderer-dbg.js負責将Button執行個體渲染成原生的HTML代碼。

深入學習SAP UI5架構代碼系列之一:UI5 Module的懶加載機制

切換到Network标簽頁,選擇任意一個Button Module加載的網絡請求,把滑鼠hover到Initiator列上,在彈出視窗就能看到一個調用棧,從中就能觀察到是index.html即Button控件的消費者,觸發了這兩個Button Module的加載。

深入學習SAP UI5架構代碼系列之一:UI5 Module的懶加載機制

在index.html裡執行個體化Button控件的代碼處設定斷點,重新重新整理應用。因為sap.ui.commons.Button并不是原生的HTML element,是以調試器執行到代碼第11行并且單步執行後,會觸發Button Module的加載:

深入學習SAP UI5架構代碼系列之一:UI5 Module的懶加載機制

這就是SAP UI5 Module的懶加載機制:如果該頁面沒有用到Button控件,則對應的Button Module永遠不會被加載。

下圖sap-ui-core-dbg.js第26384行就是Button Module的加載入口,注意注釋裡lazy stub for XXX的提示:

深入學習SAP UI5架構代碼系列之一:UI5 Module的懶加載機制

equireModule準備加載sap/ui/commons/button.js這個Module檔案:

深入學習SAP UI5架構代碼系列之一:UI5 Module的懶加載機制

Module檔案通過AJAX被加載後,SAP UI5得到的隻是純字元串文本,還無法直接用其建立button執行個體。SAP UI5會調用浏覽器原生API, window.eval(), 将button.js檔案的字元串内容傳入該API,執行結果是一個JavaScript對象,也就是SAP UI5 Button Module的運作時實體。

SAP UI5運作時為所有的Module維護了一個系統資料庫,以鍵值對的資料結構存儲了這些Module的資訊,鍵的資料類型為string,值類型即window.eval()執行加載好的JavaScript檔案内容後傳回的JavaScript對象。

Module的可能狀态為一系列枚舉值:INITIAL, LOADED, READY, FAILED, PRELOADED.

回到我的例子,因為我的代碼觸發了Button Module的第一次加載,是以代碼第16487行,将Module的狀态标注為INITIAL.

深入學習SAP UI5架構代碼系列之一:UI5 Module的懶加載機制

繼續調試:

Line 16514: 将Button Module狀态設定為LOADING.

Line 16517: 根據全局标志位window.sap-ui-loaddbg的值決定加載Button Module的普通版本還是調試版本。

Line 16520: 根據Module名稱獲得待加載Module的url.

Line 16525: 使用jQuery.AJAX加載Button-dbg.js.

深入學習SAP UI5架構代碼系列之一:UI5 Module的懶加載機制

因為該Module若不加載完成,則我們代碼裡的new sap.ui.commons.Button無法繼續下去,是以這裡的AJAX調用以同步模式進行( async = false ). 在其成功加載的回調函數裡,将Module狀态設定為LOADED, response變量包含的就是Button-dbg.js的文本内容。

Module狀态為LOADED,說明其文本内容已經加載完成,可以交給16543行的execModule函數執行了(注意該函數上面的IF條件)。

深入學習SAP UI5架構代碼系列之一:UI5 Module的懶加載機制

代碼第16612,如調試器所示:變量sScript包含的就是Button-dbg.js的文本内容,待window.eval()執行完畢後,Module的狀态設定為READY:

深入學習SAP UI5架構代碼系列之一:UI5 Module的懶加載機制

new sap.ui.commons.button這行語句看似僅僅是一個簡單的執行個體構造操作,背後卻隐藏着SAP UI5控件設計的思路。

SAP UI5的注釋寫的很清楚:首先用工廠方法建立一個新的空Button執行個體oInstance,然後再使用消費者調用new sap.ui.commons.Button時傳入的參數對oInstance進行enrich:

深入學習SAP UI5架構代碼系列之一:UI5 Module的懶加載機制

我們檢視Button Module的源代碼,發現通過JavaScript的原型繼承,Button的prototype為Control

深入學習SAP UI5架構代碼系列之一:UI5 Module的懶加載機制

檢視SAP UI5官網上對sap.ui.core.Control的說明:

Rendering: 每個SAP UI5控件都有對應的Renderer,被RenderManager調用負責生成原生的HTML代碼。

顯示/隐藏,Busy Indicator,支援關聯自定義的CSS樣式類,注冊浏覽器事件。

深入學習SAP UI5架構代碼系列之一:UI5 Module的懶加載機制

Control的原型是Element:

深入學習SAP UI5架構代碼系列之一:UI5 Module的懶加載機制

Element是SAP UI5頁面的基本元素,主要用于UI5的内部實作。

深入學習SAP UI5架構代碼系列之一:UI5 Module的懶加載機制

Element的原型是ManagedObject:

深入學習SAP UI5架構代碼系列之一:UI5 Module的懶加載機制

因為這條原型鍊過長,Jerry就不一一截圖了,大家隻需要記住結論:從Button控件出發,沿着它的原型鍊往上回溯,最後會到達BaseObject(相當于ABAP/Java裡的Object).

深入學習SAP UI5架構代碼系列之一:UI5 Module的懶加載機制

本系列下一篇文章:UI5 控件渲染機制。

感謝閱讀。