深入学习SAP UI5框架代码系列之一:UI5 Module的懒加载机制

本文是深入学习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/web/tools/chrome-devtools/network/reference#uncompressed

回到我们的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的原创文章,尽在:"汪子熙":


©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,233评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,013评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,030评论 0 241
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,827评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,221评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,542评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,814评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,513评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,225评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,497评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,998评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,342评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,986评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,055评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,812评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,560评论 2 271
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,461评论 2 266