本文是深刻学习SAP UI5框架代码系列的第二篇文章。
系列目录
- SAP UI5利用开发人员理解UI5框架代码的意义
- UI5 module懒加载机制
- UI5 控件渲染机制
- HTML原生事件 VS SAP UI5 Semantic事件
- UI5控件元数据实现细节
- UI5控件的实例数据实现细节
- UI5控件数据绑定的实现原理
- UI5控件数据绑定的三种模式:One Way,Two Way和OneTime实现原理比拟
- UI5控件ID的生成逻辑
- UI5控件的多语言(国际化,Internationalization,i18n)反对的实现原理
- XML视图里的button控件
- button控件和它背地的DOM元素
通过Jerry前一篇文章 一个用于SAP UI5学习的脚手架利用,没有任何后盾API的依赖 介绍的脚手架利用,创立一个只蕴含一个Button控件的UI5利用:
浏览器里关上,总共触发了18个申请,网络传输流量1.1MB, 页面总共加载了5.1MB资源(见下图底部紫色矩形框所示)。
顺便说一说,为什么页面加载的资源尺寸(5.1 MB)会大于网络传输的数据量(1.1 MB)?
网上有一种说法,页面加载的资源,是通过网络加载的资源,以及从浏览器缓存读取的资源总和,因而会呈现Chrome开发者工具里显示的页面加载的资源尺寸大于网络传输数据量的状况。
这种说法不完全正确。更精确的说,页面加载资源统计的是前端页面加载的所有资源,通过解压之后的原始大小。
如图,关上Chrome开发者工具的Use Large request rows选项, 就能显示出通过网络加载资源解压缩过后的原始大小,如下图所示:
以上阐明来自Google官网:
https://developers.google.com...
回到咱们的UI5利用,Ctrl+Alt+Shift+P,选中"Use Debu Sources",让SAP UI5加载调试版本的库文件:
待button显示在页面之后,关上Chrome开发者工具Sources面板,能看到sap/ui文件夹下多进去一个commons文件夹:
回顾一下咱们的脚手架利用的代码里,新建了一个命名空间sap.ui.commons下的Button控件实例:
因而运行时,SAP UI5对应的Button Module会被加载。Button-dbg.js负责Button的生命周期治理和事件响应,ButtonRenderer-dbg.js负责将Button实例渲染成原生的HTML代码。
切换到Network标签页,抉择任意一个Button Module加载的网络申请,把鼠标hover到Initiator列上,在弹出窗口就能看到一个调用栈,从中就能察看到是index.html即Button控件的消费者,触发了这两个Button Module的加载。
在index.html里实例化Button控件的代码处设置断点,从新刷新利用。因为sap.ui.commons.Button并不是原生的HTML element,所以调试器执行到代码第11行并且单步执行后,会触发Button Module的加载:
这就是SAP UI5 Module的懒加载机制:如果该页面没有用到Button控件,则对应的Button Module永远不会被加载。
下图sap-ui-core-dbg.js第26384行就是Button Module的加载入口,留神正文里lazy stub for XXX的提醒:
requireModule筹备加载sap/ui/commons/button.js这个Module文件:
Module文件通过AJAX被加载后,SAP UI5失去的只是纯字符串文本,还无奈间接用其创立button实例。SAP UI5会调用浏览器原生API, window.eval(), 将button.js文件的字符串内容传入该API,执行后果是一个JavaScript对象,也就是SAP UI5 Button Module的运行时实体。
SAP UI5运行时为所有的Module保护了一个注册表,以键值对的数据结构存储了这些Module的信息,键的数据类型为string,值类型即window.eval()执行加载好的JavaScript文件内容后返回的JavaScript对象。
Module的可能状态为一系列枚举值:INITIAL, LOADED, READY, FAILED, PRELOADED.
回到我的例子,因为我的代码触发了Button Module的第一次加载,所以代码第16487行,将Module的状态标注为INITIAL.
持续调试:
- Line 16514: 将Button Module状态设置为LOADING.
- Line 16517: 依据全局标记位window.sap-ui-loaddbg的值决定加载Button Module的一般版本还是调试版本。
- Line 16520: 依据Module名称取得待加载Module的url.
- Line 16525: 应用jQuery.AJAX加载Button-dbg.js.
因为该Module若不加载实现,则咱们代码里的new sap.ui.commons.Button无奈继续下去,因而这里的AJAX调用以同步模式进行( async = false ). 在其胜利加载的回调函数里,将Module状态设置为LOADED, response变量蕴含的就是Button-dbg.js的文本内容。
Module状态为LOADED,阐明其文本内容曾经加载实现,能够交给16543行的execModule函数执行了(留神该函数下面的IF条件)。
代码第16612,如调试器所示:变量sScript蕴含的就是Button-dbg.js的文本内容,待window.eval()执行结束后,Module的状态设置为READY:
new sap.ui.commons.button这行语句看似仅仅是一个简略的实例结构操作,背地却暗藏着SAP UI5控件设计的思路。
SAP UI5的正文写的很分明:首先用工厂办法创立一个新的空Button实例oInstance,而后再应用消费者调用new sap.ui.commons.Button时传入的参数对oInstance进行enrich:
咱们查看Button Module的源代码,发现通过JavaScript的原型继承,Button的prototype为Control:
查看SAP UI5官网上对sap.ui.core.Control的阐明:
- Rendering: 每个SAP UI5控件都有对应的Renderer,被RenderManager调用负责生成原生的HTML代码。
- 显示/暗藏,Busy Indicator,反对关联自定义的CSS款式类,注册浏览器事件。
Control的原型是Element:
Element是SAP UI5页面的根本元素,次要用于UI5的外部实现。
Element的原型是ManagedObject:
因为这条原型链过长,Jerry就不一一截图了,大家只须要记住论断:从Button控件登程,沿着它的原型链往上回溯,最初会达到BaseObject(相当于ABAP/Java里的Object).
Button->Control->Element->ManagedObject->EventProvider->BaseObject.
因而,在执行Button本人的构造函数之前,其原型链上每个节点的构造函数会顺次执行一次:
本系列下一篇文章:UI5 控件渲染机制。
感激浏览。
更多Jerry的原创文章,尽在:"汪子熙":