系列目錄
(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代碼:
在ButtonRenderer.render函數裡設置斷點,然後F5刷新頁面,斷點觸發,就可從調用棧觀察到RenderManager是如何調用ButtonRenderer執行渲染工作的。
下圖畫得有些亂,意圖是想表達,最終渲染出的HTML原始碼裡的button標籤的各個屬性,分別是由ButtonRenderer哪一行代碼實現的。
Jerry剛剛做SAP UI5開發時,了解到Renderer機制後,心裡有個疑問,SAP UI5怎麼知道button控制項的渲染器是ButtonRenderer。換言之,SAP UI5控制項和其渲染器之間的一一對應關係是如何維護的?
SAP UI5框架裡,每類控制項都各自維護了一份Metadata(元數據),其中有個getRenderer方法,返回控制項對應的渲染器名稱。
關於SAP UI5控制項元數據,本系列後續文章會介紹。
從下圖第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$作為輸入,傳入另一個Component cx-carousel, 讓其將屬性值title$作為轉盤的標題渲染,而轉盤的數據源,來自傳入的屬性items$.
因為cx-carousel是一個可重用控制項,除了顯示產品轉盤外,還可以用於顯示其他同類實體的轉盤顯示,比如折扣轉盤,促銷活動轉盤等等。因此,除了將items$和title$傳入cx-carousel之外,還需要告知後者,在轉盤內部,以何種布局邏輯顯示轉盤的每一個元素。
因此,下圖第九行通過標籤定義了一個id為#carouselItem的模板,將此id一併傳入cx-carousel. 這樣,轉盤控制項在運行時,針對轉盤數據源items$內存儲的每一個產品數據,就會按照此模板定義的布局,進行繪製。
當初Jerry學習Spartacus這個產品轉盤的設計時,覺得很親切,因為其設計思路和SAP UI5List Binding(Aggregation Binding)是一致的:
https://sapui5.hana.ondemand.com/#/topic/91f057786f4d1014b6dd926db0e91070.html
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事件。