Vue 3.5 终于在 2026 年初正式发布了!这次更新虽然没有 3.0 到 3.5 那样的颠覆性变化,但在响应式系统、开发体验和运行时性能上做了大量实质性改进。

🎥 ▶ 观看 Bilibili 视频版(22:15)

响应式系统升级

Vue 3.5 重写了响应式系统的底层实现,引入了新的 $ref 编译宏和更高效的依赖追踪机制。

1
2
3
4
5
6
// Vue 3.5 新语法
const count = $ref(0)

// 不再需要 .value
count++
console.log(count) // 1

新的 watch 语法

watch 现在支持直接传入 getter 函数数组,并且可以精确控制触发时机:

1
2
3
4
5
6
7
8
9
10
const firstName = $ref('')
const lastName = $ref('')

watch(
[() => firstName, () => lastName],
([newFirst, newLast]) => {
console.log(`姓名变更为:${newFirst} ${newLast}`)
},
{ flush: 'sync' }
)

异步组件改进

defineAsyncComponent 现在支持更精细的加载状态控制:

1
2
3
4
5
6
7
8
9
10
11
const AsyncComp = defineAsyncComponent({
loader: () => import('./HeavyComponent.vue'),
loadingComponent: LoadingSpinner,
delay: 200,
timeout: 8000,
retry: 3,
onError(error, retry, fail, attempts) {
if (attempts < 3) retry()
else fail()
}
})

实战:构建一个响应式数据面板

来看一个完整的实战案例 — 一个实时数据监控面板:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<script setup lang="ts">
const data = $ref<{ time: string; value: number }[]>([])
const isRunning = $ref(false)
const intervalId = $ref<number | null>(null)

function startCollecting() {
isRunning = true
intervalId = setInterval(() => {
data.push({
time: new Date().toLocaleTimeString(),
value: Math.random() * 100
})
if (data.length > 50) data.shift()
}, 1000)
}

function stopCollecting() {
isRunning = false
if (intervalId !== null) {
clearInterval(intervalId)
intervalId = null
}
}
</script>

迁移建议

  • 从 Vue 3.4 升级到 3.5 基本无痛,可以逐个文件启用 $ref 语法
  • 建议在新项目中直接使用 $ref,旧项目保持 ref() 以降低迁移成本
  • defineAsyncComponent 的 retry 配置在弱网环境下特别有用

Vue 3.5 是一次稳扎稳打的升级,没有花哨的新功能,但每个改进都切中开发者的实际痛点。