简体中文
蒸汽模式,即vapor,是vue3的新功能。
近年新兴的前端框架,掀起了新一轮的性能革命,纷纷去掉了虚拟DOM。通过更复杂的编译器,生成更高效的直接操作DOM的代码。
vue中去掉虚拟DOM的版本即为蒸汽模式。
回答蒸汽模式为什么更快这个问题前,我们需要先明白虚拟DOM为什么慢。
假设我们要加载一个大页面,里面有1000个DOM元素。
在蒸汽模式之前的版本,运行时的流程实际是:
本来创建1000个真实DOM的树已经不快了,再加上还要花时间创建1000个虚拟DOM树,造成页面加载更慢。
过去的虚拟DOM,包含了DOM操作的最佳实践,使得普通开发者写出的代码也能较高性能运行。
但蒸汽模式,通过更强大和复杂的编译器,把vue的语法编译成了包含DOM操作最佳实践的JS代码。
注意:蒸汽模式仅支持组合式API(setup),不支持选项式。
选项式的问题在于很多写法框的比较死,灵活度相比其他框架要弱。
从DCloud的角度看,蒸汽模式的vue框架,综合性能、生态、易用性、灵活性,已超过了react等其他框架。
uni-app x 引入蒸汽模式,不仅是去掉了虚拟DOM,更重要的是 uni-app x 全新的渲染系统。
出于减少技术概念和条件编译的角度,这套全新的渲染系统和蒸汽模式绑定推出,渲染系统仅有内部代号,没有对外单独命名。
对于开发者而言,写条件编译时仅需一个条件,即// #ifdef VUE3-VAPOR。
这个无名的渲染系统,实现了跨平台App框架的历史突破,即:基于原生渲染管线,但超越了原生的渲染速度。
在hello uni-app x的模板下,有一个4050页面,同屏渲染2050个view,里面套了2000个text,一共4050个元素。
在鸿蒙nova12(apiLevel 21)上,创建和渲染这4050个元素仅耗时300ms左右。
而原生arkui,同设备上创建相同数量的元素并渲染,需要耗时900ms左右。渲染速度快3倍。
原生arkui的开源工程见https://gitcode.com/dcloud/test4050-harmony-arkui,开发者可以自行编译体验测试。
另外我们也测试了其他跨平台框架在鸿蒙的表现,包括基于k/n方案的跨平台框架,实际运行速度比原生的arkui要慢的多,更无法与uni-app x蒸汽模式相比。
在复杂长列表中,uni-app x 蒸汽模式的丢帧率也优于原生arkui。
在120Hz高刷屏上,8.3ms内无法完成新列表项的加载,就会掉帧。列表越复杂,越难以在8.3ms内完成渲染。
而uni-app x 蒸汽模式极快的渲染速度,支撑开发者构造非常复杂的列表,也可以丝般顺滑。
关于uni-app x的蒸汽模式为什么这么快,很多人可能有疑问,比如
uni-app x 的App平台到底是自渲染还是原生渲染,那么答案是原生渲染。uni-app x 选择原生渲染是为了更好的和原生生态无缝融合、以及降低内存占用。
为什么都是原生渲染,uni-app x的蒸汽模式比原生渲染更快?
这里面涉及数千项工程优化,无法通过几句话解释清楚,但可以提供一些关键说明:
Android的compose ui也是基于原生渲染管线的,但没有使用Android自带的view、textview,而是实现了自己的组件系统。
这条路完全可行,只不过compose ui做的不太好,实际渲染速度比view体系更慢。
uni-app x 蒸汽模式,也几乎没有使用系统自带的组件,不管是textview、recycleview、viewpage...,或者是鸿蒙的arkUI相关组件,基本都没用,重写了。
这些全新的组件做到了比OS自带组件性能更高。
vue里template和style里的代码,被直接编译为优化度非常高的C代码。它的运行速度远快于arkts、kotlin及k/n。
有。包括2个:
App平台因为要编译C代码,所以真机运行的编译速度变慢不少。尤其是iOS和鸿蒙。
如果你做过c++开发的话,会感觉到回到了那个编译速度的时代。
后续DCloud也会持续研究改进该问题,提供开发期间的热更新方案。
template和style编译成C后,发行包以机器码方式存在,几乎无法再压缩。比编译成js压缩成hap包的体积大一些。
hello uni-app x有300多个页面,蒸汽模式的发行hap体积56M,之前非蒸汽模式的体积是46M。
如果你的应用页面少的话,体积变化不明显。
uni-app x 蒸汽模式,是基于原生渲染的自绘组件,几乎没有使用各平台的组件。可以很好的保持跨平台UI一致性。
下载HBuilderX 5.0+ 群测版,运行hello uni-app x的alpha分支。
该分支项目默认打开了蒸汽模式。
如果要在自己的项目下打开蒸汽模式,需要在manifest.json的可视化界面首页中勾选蒸汽模式。
The project's compatibleSdkVersion: 17 cannot be lower than the minimum compatible version 20 required by the dependencies: @dcloudio/uni-app-x-runtime.
ninja: error: failed recompaction: Permission denied。
此时需要重新运行一次。(ninja是deveco自带的c++编译器)
蒸汽模式目前仅支持鸿蒙。Android、iOS、web会陆续上线。
对比非蒸汽,蒸汽模式有一些变更调整,有一些待完成TODO,说明如下:
仅支持组合式,不支持选项式
选项式转组合式,AI可以帮忙。hello uni-app x里大量的选项式页面都是用AI转成了组合式,以适配蒸汽模式。详见
不再支持mixin
变更:因为性能原因,不支持复杂关系选择器,只支持简单的class选择器 详见
变更:css的样式隔离策略有较大调整
组件默认不受外部css同名影响,不管是页面还是全局css,外部的同名class默认都不能影响组件样式。
如需受外部影响,组件可以在 <script setup> 中 defineOptions 中定义 styleIsolation,默认值为:isolated。可以改为 app 或 app-and-page。
<script setup lang="uts">
defineOptions({
styleIsolation: 'app' // 可选值:isolated | app | app-and-page
})
</script>
styleIsolation: isolated | app | app-and-page
组件的使用方,不管是页面还是父组件,在组件使用时设置的class,仍然会作用到组件内的根节点上(需组件是单根节点)。
而如果想影响组件内部的子元素的样式,组件应该提供external-Class方案,供外部定制。
目前上述css隔离策略仅在鸿蒙平台(蒸汽模式)下生效,其他平台暂未支持蒸汽模式。
如果您想在其他平台非蒸汽模式下也启用该隔离策略,可以在manifest.json中手动配置styleIsolationVersion,注意:目前仅web平台支持该配置,其他平台暂未支持。
另外注意web平台使用external-class,也需要开启该隔离策略。
"uni-app-x": {
"vapor": true,
"styleIsolationVersion": "2"
}
新增和变更:组件样式支持external-class,废弃在属性上修改子元素css的做法。
内置组件里过去有些样式定制放在属性上了,比如checkbox过去有color属性,以后就没有了。后续都通过class来修改样式。
同时推荐组件作者也都使用class和external-class。减少属性和动态style设置子元素样式。
把样式设置放在组件属性上有诸多坏处:
external-class示例:hello uni-app x的uni_modules/uni-badge-view/components/uni-badge-view/uni-badge-view.uvue
TODO:还未实现css自定义变量
css动画不支持排版相关动画(left、top、width、height、margin、padding),请改用translateX/Y、scale等方式进行动画
pages.json
TODO:缺少组件sticky(目前可以用嵌套滚动来替代实现吸顶)
TODO:缺少组件waterflow
TODO:全局属性data-暂未实现
变更:布尔属性规范化。scroll-view等部分组件布尔属性默认值从true改为false。
新增和变更:swiper和表单组件中涉及样式的属性,从属性改为了external-class,支持更丰富的样式控制
新增:button多了loading属性和loading-class属性
变更:list-view的变化和限制
变更:swiper组件的变化
新增:view、text、image这3个组件的flatten拍平属性
拍平即不创建独立元素,而是绘制在父上。在审查元素边界时无法看到红框。
<view flatten></view>
该属性为初始化属性,不支持动态修改。
被拍平的元素存在一些限制,具体如下,可根据需要设置flatten属性。
注意:当自定义组件的单根节点是(view、text、image)时,该自定义组件会自动支持flatten属性,并将其传递给它的单根节点,如果在不符合要求的自定义组件上使用flatten属性,则会被自动忽略。
支持 flatten属性的组件(如 View、Text、Image)在逻辑上均可设置为 true 以进行“拍平”,但实际性能优化效果需满足以下条件:
仅当存在至少两个相邻元素同时设置为拍平时,才能提升性能,否则可能导致性能下降。
相邻元素包括:
uni.createSelectorQuery 不支持多根节点组件的获取
TODO:缺少animate api
TODO:缺少Drawable。dom2的view、text创建足够快且支持拍平,故优先级不高
在蒸汽模式之前,为了高性能绘制,经常不能使用view和text组件,而是需要通过Drawable对象来绘制线条和文字,这种写法无法跨平台且复杂。
在蒸汽模式后,开发者可以正常使用view和text跨平台的开发,比如hello uni-app x的模板中的日历示例,之前是Drawable绘制,现在都是拍平的text组件。
其他还有一些差异,见文档的兼容性说明。兼容性表格已经新增了HarmonyOS(Vapor)一列。