Vue 3.6 RC 升级全景:从 3.5 到 Vapor Mode 与 alien-signals
截至 Vue 3.6.0-rc.2,系统对比 Vue 3.5 与 3.6 的响应式内核、Vapor Mode、事件委托、互操作边界和渐进升级策略。

如果只看版本号,Vue 3.6 像是一次普通的次版本升级。但真正读完发布说明后,我的感受是:它更像 Vue 为下一阶段准备的一次“换发动机”。
一边是基于 alien-signals 重构的响应式内核,公开的 ref、computed、watch 用法基本不变;另一边是正式进入 RC 阶段的 Vapor Mode,它让 Vue 单文件组件可以绕过虚拟 DOM,编译为更直接的 DOM 更新逻辑。
不过,先把最重要的版本信息放在前面:
截至 2026 年 7 月 26 日,Vue 3.6 的最新版本是 3.6.0-rc.2。RC 是候选发布版,不是稳定版。本文适合用来评估、试验和准备迁移,不代表所有生产项目都应该立即升级。
先看结论:3.6 改变了什么
| 对比维度 | Vue 3.5 | Vue 3.6 RC | 对现有项目的实际影响 |
|---|---|---|---|
| 响应式系统 | 3.5 已做过内部优化 | 基于 alien-signals 大幅重构 | 常规 Composition API 写法通常不需要重写,但应回归复杂副作用与调度逻辑 |
| 默认渲染模式 | Virtual DOM | 仍然是 Virtual DOM | 单纯升级依赖不会让应用自动进入 Vapor |
| Vapor Mode | 尚未作为 3.5 的正式能力交付 | 功能集进入 RC,100% 显式启用 | 可以从单个性能敏感区域开始试验 |
| 应用体积 | 默认包含 VDOM runtime | 纯 Vapor 应用可不引入 VDOM runtime | 只有纯 Vapor 或边界清晰的场景,体积收益才容易兑现 |
| API 覆盖 | 完整 Vue 3 API 生态 | Vapor 支持 Vue API 的一个子集 | Options API、实例代理相关能力不能直接迁移 |
| VDOM / Vapor 混用 | 不适用 | 通过 vaporInteropPlugin 互操作 | 标准 props、事件、slots 已覆盖,但复杂嵌套仍需测试 |
| 事件委托 | 原生监听语义 | rc.2 起默认直接绑定;.delegate 才显式委托 | 不要沿用 rc.1 的默认委托认知 |
| 适合生产吗 | 稳定版 | 当前仍是预发布版 | 生产项目应等待稳定版和上层生态明确支持 |
一句话概括:
Vue 3.5 的亮点更接近“开发体验和 SSR 能力升级”,Vue 3.6 的核心则是“响应式内核与渲染架构升级”。
从 3.5 到 3.6:变化重心已经不同
Vue 3.5 没有破坏性变化,它带来的能力大多能直接被业务开发感知:
- 响应式 Props 解构正式稳定;
useTemplateRef()改善模板引用的组织方式;onWatcherCleanup()让 watcher 清理逻辑更自然;useId()提供 SSR 友好的稳定 ID;- 异步组件支持懒激活(Lazy Hydration);
data-allow-mismatch可以声明允许的 hydration 差异;- Deferred Teleport 与自定义元素能力得到增强。
3.6 当然也包含大量修复,但它最值得关注的两件事——alien-signals 与 Vapor——都位于框架的底层。你可能不会在业务代码里多写一个新 API,却会面对新的性能特征、编译产物和运行时边界。
这也决定了升级思路:不要只检查“代码能不能编译”,还要检查响应式行为、SSR hydration、组件互操作和真实性能。
变化一:响应式内核切换到 alien-signals
Vue 3.6 对 @vue/reactivity 做了大规模重构,其基础来自 StackBlitz 开源的 alien-signals。
对于绝大多数业务开发者,下面这些代码仍然是熟悉的 Vue:
import { computed, ref, watchEffect } from 'vue'
const price = ref(99)
const count = ref(2)
const total = computed(() => price.value * count.value)
watchEffect(() => {
console.log(total.value)
})
变化主要发生在内部:依赖如何建立、状态如何标记、计算属性何时失效、effect 如何沿依赖图传播,以及这些关系如何被清理和复用。

这张图表达的是依赖传播的概念,不是 Vue 内部数据结构的逐字段示意。
性能数字应该怎样理解
Vue 核心仓库的 alien-signals 合并 PR 给出过两类微基准结果:
- 在大量
ref、computed和 effect 实例的构造场景中,示例内存从约 2.3 MB 降至约 2.0 MB,约减少 13%; - 在“一个源变化后,大量 computed 被读取”的特定压力场景中,性能提升可以超过 30 倍。
第二个数字很亮眼,但不能直接翻译成“Vue 3.6 应用快 30 倍”。它证明的是:新的依赖传播算法在某些过去成本会随规模显著上升的图结构中,复杂度表现更好。
真实页面还包含 DOM、布局、网络、组件库、序列化和业务计算。升级前后的判断应基于自己项目的 flame chart、交互延迟、内存曲线和打包结果,而不是套用框架微基准。
哪些项目最可能感受到收益
- 大量 computed 相互依赖的数据看板;
- 高频修改、筛选和派生状态很多的编辑器;
- 长时间运行、创建和销毁大量 effect 的工作台;
- 表单字段多、验证规则和联动关系复杂的应用;
- 基于 Vue 响应式原语构建的状态管理或工具库。
普通内容页也能得到内部改进,但用户未必会感知到明显差异。
谁需要格外谨慎
如果代码只使用公开的 ref、reactive、computed、watch 与 effectScope,迁移风险相对可控。真正需要警惕的是:
- 直接读取或修改 Vue 响应式内部字段;
- 依赖未公开的 effect、Dep 或 scheduler 实现细节;
- 自行 monkey patch 响应式函数;
- 对 watcher 执行顺序、同步刷新和清理时机有隐含假设;
- 库代码同时支持多个 Vue 次版本,却没有覆盖这些边界测试。
内部重构的意义,正是 Vue 可以在保持公开 API 的同时更换实现。反过来说,依赖内部实现的代码也最容易在这类升级中暴露问题。
变化二:Vapor Mode 不再只是实验概念
Vapor Mode 是 Vue SFC 的一种新编译模式。传统 Vue 模板会生成 VNode,由 Virtual DOM runtime 对比前后两棵树,再把差异更新到真实 DOM;Vapor 则让编译器提前识别动态部分,生成更直接、粒度更细的更新逻辑。
它的目标有两个:
- 降低应用的基础包体积;
- 减少运行时创建、遍历和比较 VNode 的成本。
官方发布说明称,Vapor 已在第三方 js-framework-benchmark 中达到与 Solid、Svelte 5 相近的级别。这个结论同样应该按“基准场景”理解,而不是把不同框架、不同应用的真实性能压缩成一条排名。
Vapor 不会在升级后自动开启
Vue 3.6 依然默认使用 VDOM。要让一个 SFC 使用 Vapor,需要显式标记:
<script setup vapor lang="ts">
import { ref } from 'vue'
const count = ref(0)
</script>
<template>
<button @click="count++">
Count: {{ count }}
</button>
</template>
官方还支持两个等价入口:
<script vapor>
// <script setup vapor> 的简写
</script>
<template vapor>
<!-- 整个 SFC 使用 Vapor 编译 -->
</template>
也就是说,团队可以升级到 3.6 后继续运行现有 VDOM 应用,再有选择地迁移某个组件或页面。
纯 Vapor 应用
如果应用完全由 Vapor 组件组成,可以使用:
import { createVaporApp } from 'vue'
import App from './App.vue'
createVaporApp(App).mount('#app')
这种模式不需要引入 Virtual DOM runtime,最容易获得基础包体积收益。它更适合小型新应用、交互小工具,或可以明确约束技术栈的独立页面。
在现有 VDOM 应用中使用 Vapor
现有 createApp() 项目需要安装互操作插件:
import { createApp, vaporInteropPlugin } from 'vue'
import App from './App.vue'
createApp(App)
.use(vaporInteropPlugin)
.mount('#app')
反过来,Vapor 应用也能安装这个插件以容纳 VDOM 组件,但这样会重新带入 VDOM runtime,削弱体积优势。
Render Function 与 JSX 编写的组件仍然属于 VDOM 组件。在纯 Vapor 应用中使用它们,同样需要互操作。

我的建议与官方一致:把两种渲染模式组织成边界清楚的区域,而不是在每一层组件中来回套娃。
例如,把一个高频更新的数据画布做成 Vapor 页面或子树,周围的后台导航、弹窗和成熟组件库继续使用 VDOM。这样的收益、故障范围和回退路径都更容易测量。
rc.2 最容易踩坑的变化:事件委托改为显式启用
如果你在 rc.1 阶段已经试过 Vapor,这一节尤其重要。
rc.1 的说明中,符合条件的事件会自动委托到 document。但这与原生 DOM 和标准 Vue 的行为存在差异:如果祖先元素提前调用 stopPropagation(),事件到不了 document,子元素被委托的 handler 也不会执行。
从 3.6.0-rc.2 开始,Vapor 默认把 DOM 监听器直接绑定到元素。只有明确希望使用文档级委托时,才添加 Vapor 专用的 .delegate 修饰符:
<button @click.delegate="onClick">
保存
</button>
同时,旧的 compilerOptions.eventDelegation 已被移除。
迁移时应该做两件事:
- 删除已有的
compilerOptions.eventDelegation; - 只对数量大、事件稳定,并且传播路径已验证的监听器使用
.delegate。
这不是一个适合全局机械替换的优化。事件是否值得委托,要结合节点数量、生命周期和传播语义判断。
Vapor 与标准 Vue 的兼容边界
Vapor 的目标不是在第一天覆盖 Vue 的所有历史能力。官方明确说明,它支持现有 Vue API 的一个子集;依赖 VNode 或组件公开实例代理的功能,目前不能直接使用。
| 能力 | VDOM 组件 | Vapor 组件 |
|---|---|---|
| Composition API | 支持 | 主要编程方式 |
| Options API | 支持 | 不支持 |
app.config.globalProperties | 支持 | 不支持 |
getCurrentInstance() | 返回当前实例 | 返回 null |
| Render Function / JSX | 原生 VDOM | 仍是 VDOM,混用需要 interop |
v-memo | 支持 | 不适用 / 不支持 |
@vue:xxx 元素生命周期事件 | 支持 | 不支持 |
| 组件模板引用 | 暴露公开实例能力 | 不暴露 $el、$props、$attrs、$slots、$refs 等属性 |
| 自定义指令 | 标准指令生命周期对象 | 使用 Vapor 专用函数接口 |
slots.default() 不能再当作无副作用探测
在 VDOM 世界中,一些组件会先调用 slots.default(),检查返回内容,再决定渲染 fallback。Vapor 中调用 slot 可能直接创建 Block 和 DOM、注册响应式 effect,或在 hydration 时认领已有 SSR DOM。
因此不要这样写:
<script setup vapor>
import { useSlots } from 'vue'
const slots = useSlots()
const content = slots.default?.()
const showFallback = !content
</script>
让模板负责 slot 的实际渲染,通常更安全:
<template>
<slot />
</template>
自定义指令需要单独迁移
Vapor 自定义指令接收节点和响应式 getter,并且可以返回 cleanup 函数。它不是把 VDOM 指令的 mounted、updated、unmounted 对象原样搬过去。
如果项目或组件库依赖大量自定义指令,应该把它们列成独立迁移项,逐个验证响应式更新、清理和 SSR 行为。
Nuxt、Router、Pinia 和组件库应该怎么看
Vue 核心可用,不代表上层框架已经自动完成 Vapor 集成。
Vue 官方的 Vapor Roadmap 单独列出了 Router、Pinia、Nuxt、DevTools 和 Vue Test Utils 等生态工作,其中 Nuxt 还依赖 SSR hydration 能力。对真实项目来说,编译器能否识别 Vapor、服务端产物如何生成、客户端如何 hydration、开发工具怎样检查组件,都是完整链路的一部分。
因此我会把项目分成两类:
普通 Vue / Vite 应用
可以在分支中升级 3.6 RC,先验证现有 VDOM 模式,再挑一个叶子页面试用 Vapor。依赖关系比较直接,问题也更容易归因。
Nuxt、SSR 或重度组件库应用
不要仅通过 package override 强行把底层 Vue 换成 RC,就把它视为完成 Vapor 升级。应该先确认当前框架、构建插件和 SSR 链路明确支持对应版本,再进行 hydration、路由切换、异步组件和组件库互操作测试。
即使暂时不使用 Vapor,测试 Vue 3.6 的新响应式内核仍然有价值;只是这类试验最好留在独立分支或测试环境。
一套更稳妥的升级路线
第一阶段:只升级依赖,不启用 Vapor
普通 Vue / Vite 项目可以在实验分支中安装 RC:
pnpm add vue@3.6.0-rc.2
如果项目直接依赖 @vue/server-renderer,让它与 Vue 保持同一版本:
pnpm add vue@3.6.0-rc.2 @vue/server-renderer@3.6.0-rc.2
然后先验证原有 VDOM 应用:
- 单元测试与组件测试;
- 首屏 SSR 与客户端 hydration;
- watch、computed、effectScope 的复杂场景;
- 快速路由切换后的副作用清理;
- 自定义指令、Teleport、Suspense 和异步组件;
- 开发与生产构建;
- 浏览器控制台 warning 和错误;
- 关键交互的耗时与内存基线。
如果这一阶段失败,问题大概率来自新响应式实现或 RC 回归,而不是 Vapor,定位会简单得多。
第二阶段:选择一个边界清楚的区域
合适的试点通常同时满足:
- 使用 Composition API;
- 很少依赖组件实例;
- 不依赖复杂的 VDOM 组件库;
- 更新频率高,确实存在性能压力;
- 有独立路由或明确的组件树边界;
- 有可重复的性能测试。
先记录迁移前的 JavaScript 体积、交互延迟、CPU 时间和内存,再启用 Vapor。没有基线,就很容易把“技术上成功运行”误判成“值得迁移”。
第三阶段:验证互操作与 SSR
至少覆盖这些组合:
- VDOM 父组件嵌套 Vapor 子组件;
- Vapor 父组件嵌套 VDOM 子组件;
- props、emit 与双向绑定;
- 默认 slot、具名 slot 与作用域 slot;
- Suspense、异步组件与错误边界;
- 服务端输出、hydration 和 mismatch 恢复;
- 组件卸载后的 watcher、事件与指令 cleanup。
rc.2 的修复列表中有相当多内容正好集中在 hydration、Suspense、slot anchor 和 VDOM interop。这说明这些区域正在快速收敛,也说明它们是当前最值得测试的地方。
第四阶段:等稳定版再决定生产节奏
RC 的意义是功能集已经接近确定,接下来集中发现回归和边缘问题;它不等于生态已经完全稳定。
生产项目至少应该同时满足:
- Vue 3.6 正式版已发布;
- 使用的框架和构建工具明确支持;
- 核心组件库通过互操作验证;
- DevTools、测试工具和 SSR 链路可用;
- 性能收益足以覆盖迁移与维护成本;
- 有随时退回 VDOM 的方案。
不建议做的四件事
1. 不要把 RC 当成普通补丁版
预发布阶段的行为仍可能调整。rc.1 到 rc.2 的事件委托变化,就是最直接的例子。
2. 不要为了“用上 Vapor”迁移全部组件
导航、静态内容、低频设置页未必能获得有意义的收益。优先迁移性能瓶颈,而不是追求迁移比例。
3. 不要把微基准数字当作应用承诺
“超过 30 倍”来自特定响应式压力场景;“与 Solid、Svelte 5 同级”来自第三方基准。它们适合证明技术方向,不适合替代项目测量。
4. 不要忽略生态边界
Vue 核心、SFC 编译器、Vite 插件、Nuxt、SSR、Router、Pinia、组件库、DevTools 和测试工具共同组成开发体验。只让其中一个包进入 RC 版本,不代表整条链路已经升级完毕。
我的项目类型建议
| 项目类型 | 现在是否值得试 | 建议 |
|---|---|---|
| 小型新工具、内部实验 | 值得 | 可以尝试纯 Vapor,重点测包体积与交互 |
| 已有 Vue SPA | 值得在分支试 | 先保持 VDOM,再迁移单个性能敏感页面 |
| Nuxt / SSR 站点 | 适合研究,生产宜等待 | 先确认框架支持,重点测 hydration |
| 组件库 | 应尽早做兼容测试 | 检查实例代理、slots、自定义指令和 interop |
| 大型数据看板 / 编辑器 | 很值得压测 | 单独比较 alien-signals 与 Vapor 各自带来的收益 |
| 内容型官网 | 优先级较低 | 等稳定版和生态成熟,避免为有限收益增加复杂度 |
最后的判断
Vue 3.6 RC 最有价值的地方,不是提供了多少个可以立刻写进业务的新 API,而是同时推进了两个长期问题:
- Vue 的响应式系统能否在更复杂的依赖图中保持高效;
- Vue 的模板能否在保留熟悉开发体验的同时,摆脱必须依赖虚拟 DOM 的成本。
alien-signals 回答第一个问题,Vapor 尝试回答第二个问题。
对于现有项目,我认为最合理的策略是:先把 3.6 当作响应式内核升级来测试,再把 Vapor 当作可选的局部编译模式来评估。 两件事分开验证,才能知道性能变化来自哪里,也能把风险控制在清晰的边界内。
Vue 3.6 还没有到“所有人今天就应该升级”的阶段,但它已经到了“值得所有 Vue 团队开始理解”的阶段。
资料说明
- Vue 3.6 minor 分支 Changelog:3.6.0-rc.1 的 Vapor 总览、兼容边界,以及 rc.2 的事件委托变更。
- Vue 3.6.0-rc.2 Release:本文发布时的最新候选版本。
- Vue 3.5 发布说明:Vue 3.5 的响应式优化、SSR 与开发者 API 基线。
- Vue core:alien-signals 重构 PR:响应式实现、内存与特定压力场景微基准。
- Vapor Mode Roadmap:核心能力与 Vue 生态集成路线。
- js-framework-benchmark:Vue 官方发布说明引用的第三方前端框架基准。
本文中的升级建议是我基于官方资料和工程经验做出的判断,文章由 AI 协助资料整理与语言校对;具体项目仍应以自身测试结果为准。
留言
登录后加入讨论
你的邮箱不会公开,留言只显示昵称。