这是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$作为输出,传入另一个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的原创文章,尽在:"汪子熙":