vue3.6.0-beta.1 公测版本已发布 ,Vapor Mode 、Alien Signals 新特性
vue 3.6 + 版本还基于alien-signals对@vue/reactivity进行了重大重构,显著提升了响应式系统的性能和内存使用效率;同时完成了Vapor Mode预期功能集成!这里不对 Vapor Mode 、Alien Signals 基本介绍和使用,主要 Vapor Mode 与 VDom 的API使用差异记录:
1.生态兼容性:
虽然支持混用,但如果你在 Vapor 组件里使用依赖虚拟 DOM 的第三方组件库(比如现在的 Element Plus 或 Ant Design Vue),可能会遇到边缘 BUG。官方建议尽量保持“分区治理”,不要过度混用。
2.API 差异
1.选项式API不支持
Vapor Mode 是为 Composition API (<script setup>) 而生的。如果你还在坚持用 data(), methods() 这种 Options API 写法,Vapor Mode 暂时不支持,可能永远也不会支持。
1.app.config.globalProperties 不支持
2.getCurrentInstance() 在 Vapor 组件中会返回 null
3.Suspense 组件在 Vapor Mode 暂不支持
4.在 Vapor 模式下的模板里,不能像以前那样直接使用组件实例上“自动提供”的一些属性。
在 【传统 VDOM 模式(Vue 2 / Vue 3 默认模式)】中,Vue 会在模板里自动注入一些来自组件实例的属性,比如:$props、$slots、$attrs、$emit、$refs,因此你可以在模板中直接这样写:
<div>{{ $props.title }}</div>
<div v-if="$slots.default">有默认插槽</div>
Vapor 模式【不再创建传统的组件实例(component instance)】,或者说不再暴露这个实例给模板使用。
模板中 【不会自动存在 $props、$slots、$attrs、$emit、$refs】 等变量
模板表达式只能访问【显式提供的数据】
<!-- ❌ Vapor 模式下不可用 -->
<div>{{ $props.title }}</div>
<div v-if="$slots.default">...</div>
5.@vue:xxx 按元素级别触发的生命周期事件不支持
@vue:xxx 是 Vue 在 VDOM 模式下提供的一组“内部/底层生命周期事件”,可以直接绑定在某个 DOM 元素或组件上,用于监听这个“虚拟节点(VNode)”的生命周期。
VDOM 模式
<template>
<div
@vue:mounted="onMounted"
@vue:updated="onUpdated"
@vue:unmounted="onUnmounted"
>
这个 div 元素对应的 VNode 被挂载 / 更新 / 卸载时,触发回调
</div>
</template>
6.Vapor 模式下,自定义指令(custom directive)的“函数签名”和用法,和传统 VDOM 模式不一样。
type VaporDirective = (
// 指令作用的目标:普通 DOM 元素 | 组件
node: Element | VaporComponentInstance,
// 指令的值:在 Vapor 里你不会直接拿到 value, 而是拿到一个函数value()
value?: () => any,
// 指令参数(: 后面的部分): <div v-my-directive:params />
argument?: string,
// 指令修饰符 (. 后面的部分): <div v-my-directive.foo.bar />
modifiers?: DirectiveModifiers,
) => (() => void) | void
// vopar mode 自定义指令
const MyDirective = (el, source) => {
// 初始化逻辑
watchEffect(() => {
el.textContent = source()
})
return () => {
// 清理函数
console.log('cleanup')
}
}
特点:Vapor 指令是一个“接收节点 + 可读取值函数”的普通函数,返回值(如果有)就是卸载时的清理逻辑,不再有一堆生命周期钩子。
一个函数
一次初始化
一个清理函数: 当节点存在时做事,节点销毁时撤销事
没有 updated 钩子: 没有 diff / update 阶段
// vdom 自定义指令
const myDirective = {
created(el, binding, vnode, prevVnode) { },
beforeMount(el, binding, vnode, prevVnode) {},
mounted(el, binding, vnode, prevVnode) {},
beforeUpdate(el, binding, vnode, prevVnode) {},
updated(el, binding, vnode, prevVnode) {},
beforeUnmount(el, binding, vnode, prevVnode) {},
unmounted(el, binding, vnode, prevVnode) {}
}
app.directive('directiveName', myDirective )
注意:当 Vapor 和传统 VDOM 组件混合使用时,目前是“有限支持”,不是完全无缝。
1.Vapor 组件可以嵌套 VDOM 组件;VDOM 组件也可以嵌套 Vapor 组件;
2.目前只保证这些是可靠的:props、events、slots(基础用法),但一些极端/复杂场景还没完全处理好。
如果你在 Vapor Mode 里用:Element Plus、Ant Design Vue、Vuetify 这些库强依赖 VDOM,那你【大概率会遇到奇怪问题】(不是设计目标场景);
例如:在 VDOM 组件里:slots.default();
当 slots.default() 实际来自 【Vapor 组件】 时:【不能正常渲染】,是一个已知 bug / 限制;按照如下写法:
import { renderSlot } from 'vue'
// 必须使用 Vue 的 renderSlot 辅助函数
// slots.default() 是 VDOM slot 函数调用;Vapor slot 不是传统的 VNode 函数;interop 层没法完全模拟这种调用方式;renderSlot 是 Vue 内部“官方桥接入口”
renderSlot(slots, 'default')
3.项目中如何使用:把应用按区域隔离使用
一块区域:全 Vapor; 另一块区域:全 VDOM,如下:
App
├─ LegacyLayout (VDOM)
│ ├─ ElementPlusComponents (VDOM)
│
└─ VaporLayout (Vapor)
├─ VaporList
├─ VaporChart
而不是:Vapor → VDOM → Vapor → VDOM (❌ 不推荐)

浙公网安备 33010602011771号