這是Jerry 2020年的第79篇文章,也是汪子熙公衆號總共第261篇原創文章。html
系列目錄數組
(0) SAP UI5應用開發人員瞭解UI5框架代碼的意義框架
(1) UI5 module懶加載機制函數
(2) UI5 控件渲染機制(本文)工具
(3) HTML原生事件 VS SAP UI5 Semantic事件佈局
(4) UI5控件元數據實現細節學習
(5) UI5控件的實例數據實現細節ui
(6) UI5控件數據綁定的實現原理spa
(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$做爲輸入,傳入另外一個Component cx-carousel, 讓其將屬性值title$做爲轉盤的標題渲染,而轉盤的數據源,來自傳入的屬性items$.
由於cx-carousel是一個可重用控件,除了顯示產品轉盤外,還能夠用於顯示其餘同類實體的轉盤顯示,好比折扣轉盤,促銷活動轉盤等等。所以,除了將items$和title$傳入cx-carousel以外,還須要告知後者,在轉盤內部,以何種佈局邏輯顯示轉盤的每個元素。
所以,下圖第九行經過<ng-template>標籤訂義了一個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產品轉盤控件頁面裏,用<ng-template>定義出的id爲#carouselItem的模板一樣的角色。
感謝閱讀,本系列下一篇文章:HTML原生事件 VS SAP UI5 Semantic事件。
更多Jerry的原創文章,盡在:"汪子熙":