这篇文章主要介绍JavaScript GUI技术栈的案例分析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!
- <李> <强> JS框架层>强,可理解为一个大幅简化的Vue式JavaScript框架李> <李> <强> JS引擎与运行时层>强,可理解为一个大幅简化的WebKit式运行时李> <李> <强>图形渲染层>强,可理解为一个大幅简化的Skia式图形绘制库李>
这三个抽象层,整体构成了一套面向嵌入式硬件的GUI技术栈。不同于许多高呼“不明觉厉/深不可测”的舆论,个人认为至少对于GUI部分,国内凡是接触过目前主流混合式跨端方案或JS运行时研发的一线开发者,都很容易从源码出发来理解它。下面逐层对其做一些解读和分析。
JS框架层
从最顶层的视角出发,要想用“鸿蒙2.0”渲染出一段动态的文本,你只需要编写如下的XML(类XML)格式代码:
& lt; !——喂。hml——祝辞& lt;文本>//你好。jsexport默认{数据:{你好:& # 39;ppt # 39; }, {这个煮()。你好=& # 39;核武器& # 39;; } }复制代码
这样只要点击文本,就会调用<代码> 代码>方煮沸法,让<代码> PPT> 代码变成<代码>核武器> 代码。
这背后发生了什么呢?熟悉Vue 2.0的同学应该会立刻联想到下面这几件事:
- <李>需要对XML的预处理机制,将其转换为JS中的嵌套函数结构。这样只需在运行时做一次简单eval,即可用JS生成符合XML结构的UI。李> <李>需要事件机制,使得触发<代码> onclick 代码>事件时能执行相应回调。李> <李>需要数据劫持机制,使得对<代码>。你好> 代码赋值时能执行相应回调。李> <李>需要能在回调中更新UI对象控件。李>
这几件事分别是怎么实现的呢?简单说来是这样的:
- <李> <强> XML预处理强>依赖现成的NPM开源包,从而把XML中的<代码> onclick 代码>属性转换为JS对象的属性字段。李> <李> <强>事件的注册和触发强>都直接由c++实现。如上一步所获得的JS对象<代码> onclick 代码>属性会在c++中被检查和注册,相当于全部组件均为原生。李> <李> <强>数据劫持机制强>用JS实现,是个基于<代码> Object.defineProperty> 代码的(几百行量级的)视图模型。李> <李> <强> UI控件的更新>强,会在ViewModel自动执行的JS回调中,调用c++的原生方法实现。这部分完全隐式完成,并未开放<代码>文档。createElement> 代码式的标准化API。李>
由于大量常见JS框架中的能力都直接做进了c++,所以整套GUI技术栈里用纯JavaScript所实现的东西(主要见<代码> ace_lite_jsfwk> 代码仓库下的<代码>核心/index.js 代码>,<代码>观察者。js代码>和<代码>主题。js代码>),相当于有且只有这么一个功能:
<强>一个可以表的视图模型。强>
至于纯js框架部分的实现复杂度和质量,客观地说如果是个人业余作品,可以当作校招面试中不错的加分项。
js引擎与运行时层
理解了js框架层之后,我们既可以认为“鸿蒙2.0”选择把高度简化后的Vue深度定制进了c++里,也可以认为它紧密围绕着高度简化(且私有)的DOM实现了配套的前端框架,因此要想继续探索这套GUI的原理,我们就必须进入其c++部分,了解其js引擎与运行时层的实现。
js引擎和运行时之间,有什么区别与联系呢? js引擎一般只需符合ecma - 262规范,其中没有对任何带“副作用”的平台API的定义。从<代码> setTimeout 代码>到<代码>文档。getElementById 代码>到<代码>控制台。日志代码>再到<代码> fs。readFile> 代码,这些能执行实际IO操作的功能,都需要由“<强>将引擎API和平台API胶合到一起>强”的运行时提供。运行时本身的原理并不复杂,譬如在个人的文章《从JS引擎到JS运行时》中,你就可以看到如何借助现成的QuickJS引擎,自己搭建一个运行时。
那么在“鸿蒙2.0”中,JS运行时是如何搭建出来的呢?有这么几条重点:
- <李> JS引擎选择了JerryScript,这是一款由三星开发的嵌入式JS引擎。李> <李>每种形如<代码> & lt; text> 代码>和<代码> & lt; p> 代码的XML标签组件,都对应一个绑定到JerryScript上的c++组件类,如<代码> TextComponent 代码>和<代码> pComponent 代码>等。李> <李>除UI原生对象外,还有一系列在JS中以<代码> @system> 代码为前缀的内置模块,它们提供了JS中可用的路由器/音频/文件等平台能力(参见<代码> ohos_module_config。李h 代码>)。>
这里特别值得一提的是路由器。它和vue-router等常见网络平台路由的实现原理有很大区别,是专门在运行时内深度定制的(参见