与微信小程序类似,UNI-APP的核心底层原理也是双线程架构,但它更进一步,是一个更宏大、更完整的“编译器 + 运行时”双引擎架构-1-5。它通过编译时的转换和运行时的适配,将一套代码发布到iOS、Android、H5、以及各类小程序平台。
下面这个流程图可以帮你更直观地理解UNI-APP是如何将一套代码分发到不同平台的:
这个流程可以分解为两大核心部分:
🏗️ 编译器:多端代码的转换器
这是UNI-APP实现跨端的起点,它运行在开发环境中,负责将你的.vue 文件翻译成各平台能懂的语言-1。
-
编译过程:编译器会解析你的Vue模板、JS和CSS,生成抽象语法树(AST),然后通过一系列插件进行平台适配改造,最后输出目标代码-5。
-
输出示例:
-
关键工具:编译器支持条件编译,让你可以通过特殊的注释,为不同平台编写专属代码-1-5。UNI-APP也提供了基于Webpack(Vue2版)和Vite(Vue3版)两套编译体系-1-5。
🚀 运行时:跨端能力的执行者
当代码编译完成后,就需要在各自平台的运行时环境中执行。这个运行时主要负责解析编译后的代码,并提供跨端的API和组件。
-
逻辑层与视图层分离(非H5端) :这是UNI-APP性能的核心。它效仿了小程序的架构,将JS业务逻辑和页面渲染拆分开来-2-7-10。
-
通信桥梁(JSBridge) :逻辑层和视图层分离后,它们之间的通信就需要一个桥梁。UNI-APP通过内置的桥接层,让两端可以通过统一的JSON格式消息进行通信-3。开发者可以使用
uni.requireNativePlugin调用原生模块,或通过事件监听(uni.onNativeEventReceive)接收原生层发送的数据-3。 -
跨端API适配:你在代码中写的
uni.request、uni.getStorage等API,在运行时会被动态地映射为对应平台的实现。例如,在微信小程序中,uni.request底层调用的就是wx.request-1。
⚠️ 通信的代价与优化
逻辑层和视图层分离虽好,但也带来了通信损耗。特别是在Android低端机上,每次通信可能耗时几十毫秒-2-7。这在连续高帧率的Canvas动画或需要频繁反馈的拖拽交互中,会造成卡顿-2-7。
为了应对这个挑战,UNI-APP提供了几种“开挂”方案:
- renderjs (for App-vue & H5) :一个运行在视图层的JS。它可以直接操作视图层的DOM,处理像Canvas动画这类频繁交互的任务,完全绕开了跨层通信,实现丝滑流畅-2-7。
- wxs (for 微信小程序) :微信小程序提供的类似方案,UNI-APP也支持将其编译到微信小程序、App和H5中-2。
- bindingx (for App-nvue) :在原生渲染的nvue中,通过bindingx可以一次性将一个动画表达式传递给原生层,由原生层解析并执行,避免反复通信-2-7。
总结来说,UNI-APP的底层原理就像一个精心设计的“翻译官”和“包工头”的组合:编译时,它化身“翻译官”,将你的Vue代码翻译成各平台的本地方言;运行时,它又化身“包工头”,在幕后搭建起逻辑与渲染的双线程架构,并通过JSBridge进行调度,同时准备好各种“秘密武器”(如renderjs)来解决通信带来的性能问题。
与微信小程序专注于单一平台内的双线程通信相比,UNI-APP的架构更像是一个更宏观的跨端调度系统。它的编译器负责将一套代码转化为不同平台(包括小程序、App、H5)的本地化语言,而在App和小程序端内部,则沿用了类似的双线程模型来保证性能