乐趣区

关于javascript:深入学习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$ 作为输出,传入另一个 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 的原创文章,尽在:” 汪子熙 ”:

退出移动版