SAP UI5 xml 檢視裡定義的控制元件,執行時如何建立其例項的?

注销發表於2022-02-15

入口函式在 XMLTemplateProcessor 裡:

解析 xml 檢視的原始碼之後,呼叫 createRegularControls 進行例項建立:

這是我的 xml 檢視原始碼:

<mvc:View
   controllerName="sap.ui5.walkthrough.controller.InvoiceList"
   xmlns="sap.m"
   xmlns:mvc="sap.ui.core.mvc">
   <List
      headerText="{i18n>invoiceListTitle}"
      class="sapUiResponsiveMargin"
      width="auto"
      items="{invoice>/Invoices}">
      <items>
         <ObjectListItem
      title="{invoice>Quantity} x {invoice>ProductName}"
      number="{
         parts: [{path: 'invoice>ExtendedPrice'}, {path: 'view>/currency'}],
         type: 'sap.ui.model.type.Currency',
         formatOptions: {
            showMeasure: false
         }
      }"
      numberUnit="{view>/currency}"/>
   </items>
   </List>
</mvc:View>

number 欄位的繫結路徑被解析了出來:

在 BindingParser 的程式碼裡,上述字串型別的繫結路徑,被解析成了 json 物件:

這裡呼叫 sap.ui.model.type.Currency 的建構函式。

我們再回過頭來看 xml 檢視的載入和解析過程。

在 XMLView.js 的 this._xContent 欄位裡,我們能找到 xml 檢視的字串格式的原始碼。

在 XMLView.js 里根據字串 _xContent 進行搜尋,即可查到這個欄位賦值的位置:

在程式碼第 607 行觸發 xml 檢視檔案的載入:

從方法名也能看出,xml 檢視檔案採用非同步的方式進行載入:

loadResourceAsync(sResourceName).then(runPreprocessorsAsync).then(processView);

這裡採用了 promise 非同步程式設計模型:

        function loadResourceAsync(sResourceName) {
            return LoaderExtensions.loadResource(sResourceName, {async: true}).then(function(oData) {
                return oData.documentElement; // result is the document node
            });
        }

LoaderExtensions.loadResource 執行非同步載入 xml 檢視檔案的任務,載入成功的結果,透過輸入引數 oData 傳遞到匿名回撥函式內。

進入 loadResource 內部:

轉發給 sap.ui.loader._.getModuleContent(sResourceName, mOptions.url);


從快取裡讀取。由於是第一次載入,快取沒有命中:

最終還是用的 jQuery.ajax api 去載入的資料:

載入成功後,呼叫 335 行的 success 回撥函式:


ajax 請求的 dataType 欄位值為 xml:


載入成功的 xml document 物件:

呼叫 resolve 方法,將 xml document 傳給 promise api 的 then 回撥函式。

此處就開始遞迴地解析 xml document 的節點了:

function parseChildren(xmlNode, bRoot, bIgnoreToplevelTextNodes, pRequireContext) {
            var children = xmlNode.childNodes;
            for (var i = 0; i < children.length; i++) {
                parseNode(children[i], bRoot, bIgnoreToplevelTextNodes, pRequireContext);
            }
        }

parseChildren 呼叫 parseNode.

更多Jerry的原創文章,盡在:"汪子熙":

相關文章