深入学习SAP UI5框架代码系列之三:HTML原生事件 VS UI5 Semantic事件

简介: 深入学习SAP UI5框架代码系列之三:HTML原生事件 VS UI5 Semantic事件

这是Jerry 2020年的第80篇文章,也是汪子熙公众号总共第262篇原创文章。


系列目录


(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元素


本文将讨论SAP UI5控件的事件处理,全文会围绕下图表现出的差异来阐述。image.png先用一个简单的例子来回顾HTML原生事件处理原理。

有这样一个简单的HTML页面,里面使用了一个HTML原生button标签,通过οnclick="copyText"注册了一个名为copyText的事件处理函数。image.png点击按钮之后,响应函数copyText将Field1的值拷贝到Field2去。这个通过onclick注册的事件处理函数,在Chrome开发者工具里可以直接查看。

image.png除了onclick之外,调用浏览器原生的addEventListener方法也能给DOM元素注册事件。image.png在企业级web应用里,DOM树的结构通常都不简单。例如仅仅包含一个简单button控件的SAP UI5应用,页面渲染出来后也会自动生成5个div标签:image.png如果每个需要响应事件的控件,都使用onclick或者addEventListener给DOM元素注册一个事件处理函数,随着DOM事件处理函数数量的增加,web应用的性能会降低。因此SAP UI5引入了另一种所谓Semantic(语义)事件的概念,来完成UI5控件的事件注册和响应工作。


使用Jerry文章 一个用于SAP UI5学习的脚手架应用,没有任何后台API的依赖 提到的脚手架,开发一个只包含sap.ui.commons.button的UI5应用:image.png上图的Elements标签页里,显示的是SAP UI5应用渲染完毕后,生成的HTML原生代码。里包含的button标签的生成逻辑,我们已经在前一篇文章 深入学习SAP UI5框架代码系列之二:UI5 控件的渲染器 里介绍过了。


我们采用与前一个原生HTML button例子同样的操作方式,在Chrome开发者工具里检查UI5应用里该button的Event Listeners,却什么也没发现。


选中"Ancestors"前面的勾之后,一下子显示了很多条目出来:image.png展开条目中的click,发现SAP UI5把click事件注册在button标签的父节点,即id为content的div标签上了,如下图所示。image.png再看看UI5应用里sap.ui.commons.Button的事件注册代码:image.png这里并没有出现HTML原生事件click的身影,而将一个包含了属性名称press,值为JavaScript函数的JavaScript对象,作为输入参数,传入了UI5 Button的构造函数里:image.png户点击这个按钮时,触发的应该是名称为click的事件,和我们在这里为press事件注册的处理函数有什么关系?


在UI5 button的实现源代码里能找到答案。切换到Chrome开发者工具的Sources标签页,快捷键Ctrl + O,输入button,选择第一个结果Button-dbg.js:image.png里能看到,press作为button支持的事件,定义在Button-dbg.js里:image.png下面这段代码的含义是,当UI5 button有click事件发生时,如果其本身处于enabled并且是visible状态,则fire一个Press事件(this.firePress()):image.png因此,正是Button实现里的这个onclick函数,实现了从事件click映射到事件press的任务。image.png上图调试器里168行的this.firePress调用,最终如何成功地调用到UI5程序里针对press事件注册的处理函数的呢?


还记得这个系列的前一篇文章 深入学习SAP UI5框架代码系列之一:UI5 Module的懒加载机制 里介绍的一个知识点吗?


SAP UI5运行时为所有的Module维护了一个注册表,以键值对的数据结构存储了这些Module的信息,键的数据类型为string,值类型即window.eval()将加载好的JavaScript文件内容作为输入参数,执行后返回的JavaScript对象。


类似的原理,SAP UI5里每个控件都维护了一个键值对结构的事件注册表mEventRegistry, 键的数据类型string,存储事件名称,值类型为数组,里面存放了针对该事件,应用程序实现的响应函数。


下图展示的是我脚手架应用里的button控件的事件注册表,只包含一条记录,键为press,值为一个数组,里面唯一的元素即我在脚手架应用里实现的包含了alert调用的事件响应函数。image.png下图展示的逻辑是:

(1) SAP UI5框架从第237行的控件事件注册表里,根据事件名称press,取出存放其事件处理函数的数组;

(2) 遍历该数组,在for循环里用JavaScript function原型提供的call方法,对这些响应函数进行调用,完成事件响应:

image.png至此又引出了一个新的问题:button控件的事件注册表mEventRegistry里的那唯一的条目,是何时填充进去的?


再回忆本系列第一篇文章里介绍的SAP UI5控件的原型链:


Button->Control->Element->ManagedObject->EventProvider->BaseObject.


UI5应用里这一行语句:


new sap.ui.commons.Button()


会依次执行控件原型链上每一个节点对应的构造函数。控件事件注册表mEventRegistry的填充操作,就发生在EventProvider这个节点的构造函数里:image.png上图的变量oValue,就是我new一个button实例时传入的press事件的处理函数。在第1192行代码里,调用attachPress将oValue指向的函数进行注册。函数attachPress最终调用EventProvider的attachEvent方法,将键值对写入mEventRegistry:image.png至此有最后一个问题还未解答:本文开头部分展示的Chrome开发者工具里,SAP UI5页面渲染后生成的button标签,在Event Listeners一栏里观察不到任何响应函数。而在其父节点,id为content的div标签里,在click事件下却能观察到响应函数。


Button父节点的div标签上的click方法,和本文讨论了这么长时间的button事件注册表里的press事件,到底有何关系?


按钮被点击时,查看调试器里显示的调用栈最外一层,发现SAP UI5的jquery-dbg.js, 响应的是HTML原生的click事件,且触发该事件的对象的的确确是id为content的div标签,而不是button标签,这一点可以从event.currentTarget的值来确认。image.png以上图调用栈中绿色的线为分隔,绿线下方的代码,处理的是HTML原生的点击事件click,同时完成了将click事件,经div投递给其子节点,button标签的任务。


绿线上方的Button.onclick, 前文我们已经阐述过,通过this.firePress将click事件映射成press事件,后续SAP UI5的所有事件处理,均围绕这个press事件进行。


按照SAP UI5开发团队大佬Andreas Kunz的介绍,button这种press事件称为Semantic事件。同HTML原生的click事件直接通过onclick或addEventListener注册在HTML DOM元素上不同,Semantic event的注册和调用都是通过SAP UI5框架的JavaScript代码施加在SAP UI5自行实现的控件上,比HTML原生的DOM事件处理和响应轻量得多,能避免随着DOM树复杂度的增加而造成的应用性能下降。image.png引入Semantic事件后,UI5控件不直接响应HTML原生事件,而是通过一个叫做UIArea的实体,来接收用户触发的HTML原生事件,并将其dispatch给UI5控件,后者再将其映射成一一对应的Semantic事件,并调用应用程序里实现的响应函数。这里的UIArea可以类比成设计模式里的Facade(外观)模式,对SAP UI5的应用开发人员屏蔽了底层事件映射的复杂度。


上图的UIArea的详细描述,在SAP UI5官方文档里有记载。


下图高亮的一段对UIArea的阐述,展开来讲就是Jerry本文的内容,大家感兴趣的可以移步这个链接继续阅读。image.png如果把本文提到的Semantic事件换个叫法,比如称其为虚拟事件,那么很容易联想到Angular,Vue和React里引入的Virtual DOM(虚拟DOM)概念。从本质上说,这些前端框架都采取增加框架实现复杂度的代价,引入一个中间抽象层,来减少直接在JavaScript层操作DOM层造成的性能开销。


顺便说一句,AngularJS里的控件注册实现,同SAP UI5思路一致:同样未采取将事件处理函数直接注册到HTML DOM元素上的机制。


下图是一个Angularjs应用,第22行的ng-click指令,告诉Angularjs框架,超链接被点击后,根据模型字段name,进行排序。image.pngAngularjs框架如何解析这个ng-click指令,并完成事件注册的?

在Angularjs应用bootstrap阶段,框架会遍历HTML DOM tree,递归调用compileNodes方法,逐一解析每一个包含了ng指令的元素:

image.png当解析到包含了ng-click = "sortField = ‘name’"的a标签时,调用Angular元素element的on方法,进行事件注册:

image.png查看on方法的实现代码可知:Angularjs也并未将事件响应函数注册到DOM元素上,而是同SAP UI5一样,在框架内维护了一个控件事件注册表,this.$$listeners(SAP UI5的名称叫做mEventRegistry),采用键值对的数据结构,来存储事件名称和其对应的事件响应函数。image.pngAngularjs应用里,事件响应函数被调用时的调用栈截图:

image.png关于SAP UI5和Angularjs的事件处理机制比较的更多细节,可以参考我的SAP社区博客:


Compare Event handling mechanism: SAPUI5 and Angular


本系列下一篇文章介绍的内容:UI5控件元数据实现细节。


感谢阅读。


系列目录


(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控件



相关文章
|
2月前
|
人工智能 前端开发 搜索推荐
前端UI框架的发展:从混沌到秩序的演变
前端UI框架的发展:从混沌到秩序的演变
|
2月前
|
前端开发 JavaScript API
SAP UI5 sap.ui.require.toUrl 的作用介绍
SAP UI5 sap.ui.require.toUrl 的作用介绍
|
2月前
|
JSON 前端开发 测试技术
SAP UI5 sap.ui.core.util.MockServer.simulate 方法介绍
SAP UI5 sap.ui.core.util.MockServer.simulate 方法介绍
使用 SAP UI5 Event Bus 机制,修复 SAP UI5 分页显示数据的一个 bug 试读版
使用 SAP UI5 Event Bus 机制,修复 SAP UI5 分页显示数据的一个 bug 试读版
|
2月前
|
XML 前端开发 JavaScript
深入介绍 UI5 框架里 Smart Field 控件的工作原理
深入介绍 UI5 框架里 Smart Field 控件的工作原理
|
18天前
|
小程序 开发者 Windows
轻量、可靠的小程序 UI 框架 -- Vant Weapp的安装和使用
轻量、可靠的小程序 UI 框架 -- Vant Weapp的安装和使用
16 1
|
10天前
uniapp 安装插件 uView (多平台快速开发的UI框架)
uniapp 安装插件 uView (多平台快速开发的UI框架)
12 0
|
2月前
|
监控 测试技术
SAP 电商云修改 Product Catalog Staged 版本数据后,同步到 online 版本的 UI 操作
SAP 电商云修改 Product Catalog Staged 版本数据后,同步到 online 版本的 UI 操作
什么是 SAP ABAP 里的 Subscreen
什么是 SAP ABAP 里的 Subscreen
什么是 SAP ABAP 里的 Subscreen
|
2月前
|
Web App开发 开发框架 前端开发
Open UI5 前端开发框架配套的 Mock Server 工作原理解析
Open UI5 前端开发框架配套的 Mock Server 工作原理解析