深入学习SAP UI5框架代码系列之二:UI5 控件的渲染器
這是Jerry 2020年的第79篇文章,也是汪子熙公眾號總共第261篇原創文章。
系列目錄
(0)?SAP UI5應用開發人員了解UI5框架代碼的意義
(1)?UI5 module懶加載機制
(2) UI5 控件渲染機制(本文)
(3) HTML原生事件 VS SAP UI5 Semantic事件
(4) UI5控件元數據實現細節
(5) UI5控件的實例數據實現細節
(6) UI5控件數據綁定的實現原理
(7) UI5控件數據綁定的三種模式:One Way,Two Way和OneTime實現原理比較
(8) UI5控件ID的生成邏輯
(9) UI5控件的多語言(國際化,Internationalization,i18n)支持的實現原理
(10) XML視圖里的button控件
(11) button控件和它背后的DOM元素
使用Jerry的文章 一個用于SAP UI5學習的腳手架應用,沒有任何后臺API的依賴,創建一個只包含一個button控件的SAP UI5應用,用Chrome開發者工具里的Elements工具欄查看該button控件的原生HTML代碼:
在Jerry的前一篇文章 深入學習SAP UI5框架代碼系列之一:UI5 Module的懶加載機制,我們已經了解到UI5 Button Module之一,ButtonRenderer,專門負責將sap.ui.commons.button的實例數據,渲染成原生的HTML代碼。
在ButtonRenderer.render函數里設置斷點,然后F5刷新頁面,斷點觸發,就可從調用棧觀察到RenderManager是如何調用ButtonRenderer執行渲染工作的。
下圖畫得有些亂,意圖是想表達,最終渲染出的HTML源代碼里的button標簽的各個屬性,分別是由ButtonRenderer哪一行代碼實現的。
Jerry剛剛做SAP UI5開發時,了解到Renderer機制后,心里有個疑問,SAP UI5怎么知道button控件的渲染器是ButtonRenderer。換言之,SAP UI5控件和其渲染器之間的一一對應關系是如何維護的?
SAP UI5框架里,每類控件都各自維護了一份Metadata(元數據),其中有個getRenderer方法,返回控件對應的渲染器名稱。
關于SAP UI5控件元數據,本系列后續文章會介紹。
從調試器里能觀察到button控件元數據里,變量_sRendererName維護了button渲染器的名稱:sap.ui.commons.ButtonRenderer. 然而,這個變量在何時賦的值?
從下圖第42971行能夠看出:控件的渲染器滿足命名規范:<控件名稱>+ “Renderer”, 一個簡單的字符串拼接操作。
RenderManager在哪些時刻會開啟控件的重繪?
讓我們對腳手架應用里的button點擊事件處理函數稍作修改:每次點擊按鈕時,調用setText修改button的text屬性:
點擊按鈕,發現ButtonRenderer.render再次被觸發。
原因在于,oButton1.setText最終會調用button原型鏈上的ManagedObject.setProperty方法,該方法內部有一個顯式的invalidate調用。
如果忘記了SAP UI5控件的原型鏈設計,可以查看Jerry之前的文章:深入學習SAP UI5框架代碼系列之一:UI5 Module的懶加載機制。
Control.invalidate內部經過計算,會得出當前頁面需要重繪的區域,最終調用RenderManager進行重繪。
我們再來簡單了解下Angular里的控件繪制。以SAP Spartacus的產品轉盤(Product Carousel)顯示控件為例: 最暢銷的產品共有12款,分多屏顯示在轉盤控件里,每屏顯示若干個產品。通過控件提供的左右箭頭,進行屏與屏之間的切換。轉盤底部的小紅點,表示當前轉盤顯示的是第幾個屏幕的數據。
SAP UI5也能實現類似的復合控件,官方稱呼為Custom Control.
Spartacus產品轉盤控件的HTML代碼表現形式為標簽cx-product-carousel,內部重用了另一個自定義標簽cx-carousel:
當前顯示在屏幕里的產品信息,通過cx-carousel標簽里三個class為item active的div標簽顯示。
這個自定義產品轉盤控件通過Spartacus里的Angular Product Carousel Component實現。
Product Carousel Component的layout實現里,將Component自身的屬性items和title和title和title作為輸入,傳入另一個Component cx-carousel, 讓其將屬性值title作為轉盤的標題渲染,而轉盤的數據源,來自傳入的屬性items作為轉盤的標題渲染,而轉盤的數據源,來自傳入的屬性items作為轉盤的標題渲染,而轉盤的數據源,來自傳入的屬性items.
因為cx-carousel是一個可重用控件,除了顯示產品轉盤外,還可以用于顯示其他同類實體的轉盤顯示,比如折扣轉盤,促銷活動轉盤等等。因此,除了將items和title和title和title傳入cx-carousel之外,還需要告知后者,在轉盤內部,以何種布局邏輯顯示轉盤的每一個元素。
因此,下圖第九行通過標簽定義了一個id為#carouselItem的模板,將此id一并傳入cx-carousel. 這樣,轉盤控件在運行時,針對轉盤數據源items$內存儲的每一個產品數據,就會按照此模板定義的布局,進行繪制。
當初Jerry學習Spartacus這個產品轉盤的設計時,覺得很親切,因為其設計思路和SAP UI5 List Binding(Aggregation Binding)是一致的。
SAP UI5官網上講解List Binding的一個例子:
有一個companies JSON數組:
將companies路徑傳入List控件,完成了數據源的指定,通知List去繪制companies數組里的數據。具體渲染哪些數據?List不知道,需要items子控件來定義,比如子控件的title屬性,顯示JSON數組的name字段,description屬性,顯示JSON數組的city字段。List會根據JSON數組里的company節點的個數,動態創建對應數目的items子控件。
這里的SAP UI5 items子控件,扮演的就是本文之前介紹的Spartacus產品轉盤控件頁面里,用定義出的id為#carouselItem的模板同樣的角色。
感謝閱讀,本系列下一篇文章:HTML原生事件 VS SAP UI5 Semantic事件。
更多Jerry的原創文章,盡在:“汪子熙”:
總結
以上是生活随笔為你收集整理的深入学习SAP UI5框架代码系列之二:UI5 控件的渲染器的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: VB.net byval和byref
- 下一篇: 如何找到ngrx action匹配的取数