返回专题首页

Vue 专题

Vue3 响应式原理:Proxy、ref、reactive、computed 与 effect 机制

如果说 Vue2 的响应式原理是理解存量项目和历史限制的关键,那么 Vue3 的响应式原理,就是理解现代 Vue 项目写法和组合式 API 体验的核心。很多人会感觉 Vue3 用起来“更自然”,并不是因为只是 API 换了名字,而是因为它在底层追踪模型上做了很大调整。

Vue 专题第 08 篇 / 26 篇6 分钟

如果说 Vue2 的响应式原理是理解存量项目和历史限制的关键,那么 Vue3 的响应式原理,就是理解现代 Vue 项目写法和组合式 API 体验的核心。很多人会感觉 Vue3 用起来“更自然”,并不是因为只是 API 换了名字,而是因为它在底层追踪模型上做了很大调整。

这一篇重点要看的是:

  • 为什么 Vue3 要从 Object.defineProperty 转向 Proxy
  • refreactive 分别适合建什么状态;
  • computed 和 effect 机制在依赖系统里承担什么角色;
  • 把这些原理放回项目设计时,怎样帮助你写得更稳。

Vue3 为什么要改响应式底层?

最直接的原因,是 Vue2 那套方案在对象新增属性、数组索引、深层结构追踪这些地方天生受限。Vue3 改用 Proxy 后,数据代理的粒度和能力边界都发生了变化:

  • 拦截更自然;
  • 对对象和数组行为更统一;
  • 不再像 Vue2 那样严重依赖初始化时就把所有属性声明齐;
  • 更容易支撑组合式 API 的灵活组织方式。

所以 Vue3 的进步,不只是“语法现代化”,而是底层能力和上层组织方式一起升级了。

Proxy 相比 Vue2 的优势到底是什么?

Proxy 的最大价值,不在于名字更新潮,而在于它代理的是“对象整体访问行为”,而不是像 Vue2 那样主要围绕已有属性一个个定义 getter/setter。

这会带来几个很现实的好处:

  • 对新增属性和删除属性的感知更自然;
  • 对数组索引变化、长度变化等场景支持更完整;
  • 对响应式对象的操作模型更统一;
  • 更方便围绕依赖追踪建立现代化的组合式 API 体系。

这也是为什么 Vue3 写状态时,你会明显感觉“很多 Vue2 时代要绕的坑没那么常见了”。

refreactive 到底应该怎么选?

这是 Vue3 响应式里非常高频、也最容易被写成“经验口诀”的问题。更成熟的理解应该回到状态形态上。

ref 更适合单值或需要明确包裹边界的状态

比如:

  • 数字;
  • 字符串;
  • 布尔开关;
  • 某个局部对象引用;
  • 需要在组合函数之间清晰传递的值。

它的好处是边界非常明确,一看到就知道这是一份独立响应式值。

reactive 更适合结构化对象状态

比如:

  • 表单模型;
  • 查询参数对象;
  • 多字段联动状态;
  • 某个局部页面配置对象。

它更适合那些本来就天然以对象形式存在的状态。

真正重要的是状态建模

不要把 refreactive 理解成“两个随便选的写法风格”。它们背后反映的是你对状态形态的判断:这是一份单值状态,还是一份结构化状态。

computed 为什么不是“语法简写”?

很多人第一次学 computed,会觉得它只是模板里少写一点逻辑的工具。其实它的真正价值在于:把“由其他响应式状态推导出的结果”从副作用里分离出来。

也就是说,computed 适合表达:

  • 某个按钮是否可点;
  • 某组展示文案是否成立;
  • 当前筛选条件是否完整;
  • 页面是否处于某种复合状态;
  • 列表是否应该显示空状态。

这类逻辑的特点是:它们本身不是副作用,只是派生结果。把这些东西写成 watch 或放进杂乱的方法里,页面会越来越难解释。

effect 机制到底在做什么?

Vue3 响应式系统的核心之一,就是“某段逻辑执行时,会记录自己依赖了哪些响应式数据;当这些依赖变化后,再把这段逻辑重新触发”。从整体上看,这就是 effect 思维。

你可以把它理解成:

  • 状态访问时登记依赖;
  • 状态变化时派发更新;
  • 渲染、计算属性和某些响应副作用都建立在这套机制上。

这意味着 Vue3 响应式不是孤立的几个 API,而是一套围绕依赖追踪组织起来的运行体系。理解这一点后,你再看 refcomputedwatchEffect,就不会觉得它们只是互不相关的工具箱。

Vue3 响应式对组合式 API 有什么支撑?

这其实是最值得建立的整体认知。Vue3 之所以能让状态、计算、监听和逻辑组合得更自然,很大程度上就是因为响应式模型更适合被拆到函数级别组织。

也就是说,在组合式 API 里你更容易:

  • 按业务能力抽出状态和逻辑;
  • 在 composable 里组织请求、权限、表单、分页等局部能力;
  • 保持状态和依赖边界更清楚;
  • 让同类逻辑在多个组件间复用,而不是靠 mixin 那种容易冲突的方式。

所以 Vue3 响应式原理和 Composition API 不是两件分开的事,而是一体两面。

把 Vue3 响应式放回项目里,最重要的是什么?

最重要的不是记住每个 API 的用法,而是学会这套判断:

  • 这份状态应该是单值还是结构化对象?
  • 这是派生结果,还是副作用?
  • 这段逻辑应该放组件内部,还是提取成 composable?
  • 当前写法是在顺着响应式系统走,还是在和它对抗?

只要这套判断清楚,Vue3 项目就会自然很多。反过来,如果只是把 Vue2 写法机械搬过来,即便用了 Vue3,也很容易写出“新语法下的旧问题”。

最常见的几个误区

1. 把 refreactive 当成纯风格选择

本质上它们是在表达不同状态形态。

2. 本该用 computed 的派生结果,却写成 watch

这会让简单逻辑变成副作用逻辑。

3. 组合式 API 写了很多,但没有按能力拆分

最后只是把 Options API 的混乱搬进 setup

4. 只会调用 API,不理解依赖追踪

出现状态更新异常时就会缺少解释能力。

总结

Vue3 响应式原理真正带来的,不只是写法变化,而是一套更自然的状态代理和依赖追踪模型。Proxy 让对象和数组追踪更统一,refreactive 让状态建模更清晰,computed 负责表达派生结果,而 effect 机制则支撑了整套渲染和响应更新体系。只要把这些能力放回“状态建模、派生逻辑、副作用边界、组合式组织”这条主线上理解,Vue3 的很多设计就会真正开始变得顺手。