XML DOM 獲取節點值
666
2022-05-30
Jerry 前一篇文章 深入掌握 SAP Fiori Elements 工作原理系列之二:如何給 Fiori Elements 應用添加自定義按鈕 介紹了如何給 SAP Fiori Elements 應用的 Smart Table 工具欄里,新增自定義按鈕,并實現其點擊事件處理函數。
本文 Jerry 繼續介紹 SAP Fiori Elements 應用里,Smart Table 控件的渲染原理。根據前一篇文章介紹的知識,SAP Fiori Elements List Report 的模板,包含了 SmartTable.fragment.xml 這個頁面片段:
而該頁面片段的源代碼里,使用了 Smart Table 控件:
為了把和 Smart Table 控件不相關的依賴都剝離開,以便于大家把注意力聚焦在 Smart Table 本身上,本文 Jerry 另外開發了一個 SAP UI5 應用,只包含一個最簡單的 XML 視圖,里面使用到了 Smart Table 控件。同時,我開發了一個簡單的 Mock 服務器,讓該應用在請求 OData 服務元數據時,由 Mock 服務器把本地工程事先準備好的 metadata.xml 文件的內容,作為元數據響應,直接返回給應用。這樣我可以方便地修改本地 metadata.xml 文件,來達到各種測試目的。
關于如何在 SAP UI5 應用里手動搭建 Mock 服務器,請參考我這篇文章:何以 mock server 的方式本地啟動 SAP UI5 應用,使它不連接遠程服務器端的 OData 服務.
本文這個用于演示 Smart Table 控件使用方法的 SAP UI5 應用,其完整源代碼在我的 Github 上。
該應用三個核心文件:
metadata.xml: 該文件的內容即 OData 服務的元數據,包含加上了 SAP Fiori Elements 系列的自定義注解,我們稍后會詳細研究該文件內容。當 SAP UI5 應用向服務器發起 OData 服務元數據請求時,該請求被 Mock 服務器攔截,后者將 metadata.xml 的內容作為 OData 服務元數據響應,返回給應用。
Products.json: 測試數據 (Mock Data). 當 SAP UI5 應用準備渲染 Smart Table 待顯示的業務數據時,會向遠端服務器發起 OData batch 請求。該請求同樣會被 Mock 服務器攔截,并將該 Products.json 的內容返回給應用。
server.js: Jerry 開發的 Mock 服務器實現。
XML 視圖里定義了一個 Smart Table 控件,第 10 行代碼 entitySet=“Products”, 意思是讓該控件,在運行時"智能地" 將名稱為 Products 的 OData 模型里,所有符合某種條件的字段,渲染成表格列項目。
這個包含了 Smart Table 控件的 SAP UI5 應用,最終渲染成包含如下三列的表格:產品 ID,價格 (含金額和貨幣單位) 以及產品名稱。
我們打開 metadata.xml, 找到了 Product 模型包含的四個屬性字段。這四個屬性字段,都作為最后渲染出的列項目的備選字段。其中 Price 字段,通過屬性 sap:unit, 和 CurrencyCode 字段關聯起來,作為同一個表格備選列項目,其工作原理在 Jerry 之前的文章 深入掌握 SAP Fiori Elements 工作原理的前提條件:理解 Smart Field 里介紹過。
盡管 Product 模型包含了 4 個字段作為表格備選列項目,但為什么最終渲染出的頁面里,我們只看到了 3 個行項目?名為 Category 的字段為什么沒能渲染成行項目?
答案在 metadata.xml 的注解區域。
SAP 幫助文檔提到,其所屬的 OData 模型被注解 com.sap.vocabiularies.UI.LineItem 修飾,且類型為 com.sap.vocabularies.UI.DataField 的字段,在運行時會被 SAP UI5 框架繪制成表格列項目。
為了驗證這個結論,我們對 metadata.xml 里的元數據進行一些修改。比如現在只定義兩個表格列項目,分別為ProductId 和 Name. 同時,我用 sap:label, 給屬性 ProductId 分配標簽為 “Jerry產品ID”:
運行時的效果:Name 列表項出現在 ProductId 的左邊,因為其在元數據里的定義,位置在 ProductId 之前。
至此我們已經了解了 Smart Table 表格列項目渲染的邏輯,最后來看看源代碼實現。
我的 UI5 應用里,使用了 Smart Table 控件的 XML 視圖,運行時被加載后,會被 SAP UI5 的 XML 模板解析器, XMLTemplateProcessor 的方法 parseTemplate 所解析。XML 視圖包含的 XML 字符串,會被反序列化成 DOM 并進行遍歷。當模板解析器遍歷 DOM 過程中,遇到 SmartTable 標簽時,調用 SmartTable.init 方法,進行初始化操作:
根據本文前半部分的介紹,我們已經知道:如果缺乏 OData 元數據提供的注解,Smart Table 控件無法知道該怎么渲染表格的列項目。因此,SmartTable.js 也在 “OData 服務元數據成功取回” 這個事件上,注冊了一個鉤子函數 _onMetadataInitialised. 當 OData 服務的元數據取回之后,該回調函數被調用:
在該回調函數執行的上下文里,因為 OData 服務元數據已經處于可訪問狀態,所以 Smart Table 有足夠的信息,能夠開始渲染邏輯的執行:
下圖第 97 行的高亮代碼,getLineItemAnnotation, 即是 Smart Table 控件,準備從 Product 這個 EntityType 里,解析出符合表格列項目渲染要求的字段列表:
注意下圖第 1909 行硬編碼的字符串 com.sap.vocabularies.UI.v1.LineItem, 這就是 UI5 框架代碼里查找 Smart Table 待渲染列表項字段的依據。最后解析出的兩個列表項字段,Name 和 ProductId,就存儲在函數返回變量 oResolvedAnnotation.
有了這個信息,Smart Table 就知道該渲染哪些字段作為表格列項目了。
至此,本文已經完成了 Smart Table 控件渲染表格列項目的原理介紹,以及相應的 SAP UI5 框架是如何解析待渲染列項目的源代碼實現的介紹。
七年前,Jerry 剛剛從 ABAP 開發轉到 SAP UI5 開發時,對本文介紹的這些注解概念,理解得似是而非,因為之前用的 ABAP 這門編程語言,無法像 Java 和 TypeScript 那樣,能夠從語言層面提供對注解的原生支持。
后來接觸了 Java Spring 框架,再加上最近使用 Angular 做開發后,對注解的理解也比之前單純閱讀 SAP 文檔要深入一些了。在 Java,Angular 和 SAP Fiori Elements 里,雖然這些注解的語法有差異,但目的都一致,即提供一種對注解的目標對象,進行額外數據標注的功能。
比如 Component 是 Angular UI 最基本的組成單元,而 Component 的定義,無非就是普通的 TypeScript class,加上 @Component 注解的修飾而成。該注解能維護 Component 的元數據,告訴 Angular 框架,該 Component 在運行時應該如何被實例化和使用。
希望本文能幫助大家更好地理解 SAP 幫助文檔上對 SAP Fiori Elements 相關 OData 注解的介紹內容。感謝閱讀。
HTML JavaScript web前端
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。