入口函式在 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的原創文章,盡在:"汪子熙":