Vue 3 深度解析:Ref vs Reactive 到底怎么选?

Vue 3 深度解析:Ref vs Reactive 到底怎么选?

在 Vue 3 的组合式 API 中,refreactive 是构建响应式数据的基石。虽然它们都能驱动视图更新,但在实际开发中,选择不当往往会引发“数据变了视图没动”的坑。

本文将通过多维度对比,带你彻底掌握这两个 API。


1. 基本用法速览

Ref (Reference)

  • 适用:任何类型(基本类型 + 引用类型)。
  • 特点:逻辑层需要通过 .value 访问,模板中自动解包。
const count = ref(0);
const user = ref({ name: 'Alice' });

count.value++; // 修改方式

Reactive

  • 适用:仅限复杂类型(对象、数组、集合)。
  • 特点:直接访问属性,不需要 .value
const state = reactive({ count: 0, name: 'Alice' });

state.count++; // 修改方式


2. 核心区别对比

特性 ref reactive
底层实现 RefImpl 类(内部对对象调用 reactive) ES6 Proxy 直接代理
重新赋值 支持(直接替换 .value 不支持(直接赋值会丢失响应性)
解构支持 需要使用 toRefs 保持响应性 直接解构会丢失响应性
适用场景 计数器、字符串、单个对象、数组 复杂的表单、聚合的状态对象

3. 进阶探讨:如何实现“整体替换”?

这是开发中最容易出错的地方。当我们从后端获取一个全新的对象并想替换现有状态时:

❌ 致命错误:直接对 Reactive 赋值

let state = reactive({ name: 'Alice' });
// 错误:这会让 state 指向一个新普通对象,旧的 Proxy 代理失效,视图不再更新
state = { name: 'Bob' }; 

⚠️ 折中方案:使用 Object.assign

正如你所发现的,可以用 Object.assign 来避免丢失响应性:

const state = reactive({ name: 'Alice', age: 25 });
const newData = { name: 'Bob' };

Object.assign(state, newData); 

但是,这个方案有两个明显的缺陷:

  1. 无法删除属性:如果 state 原本有 age,而 newData 里没有,赋值后 age: 25 依然会残留在 state 中。
  2. 代码心智负担:你需要时刻记住哪些对象需要用 assign 覆盖。

✅ 最佳实践:首选 ref 进行整体替换

如果你的数据经常需要从后端获取并整体更新,ref 是唯一优雅的选择

const state = ref({ name: 'Alice', age: 25 });

// 整体替换:简单、直接、安全
state.value = { name: 'Bob' }; 
// 此时旧的 age 属性会随旧对象一起销毁,响应性完美保持。


4. 总结与建议

在 Vue 3 社区中,目前的趋势是 “Ref First”(优先使用 Ref):

  1. 基本类型:必须用 ref
  2. 对象/数组:优先用 ref,因为它的 .value 能够清晰地提醒你这是一个响应式变量,且在整体替换数据时非常方便。
  3. 聚合状态:如果你有一组高度相关的表单字段(如 form.name, form.email),使用 reactive 可以让代码看起来更像原生 JS。
  4. 解构注意:无论用哪个,解构时记得用 toRefs(state),否则响应性会“断开”。

一句话口诀
简单数据用 ref,复杂替换也用 ref
只有当你想把一堆数据“打包”且不打算换包装袋时,才考虑 reactive


posted @ 2026-01-02 14:26  雨中遐想  阅读(3)  评论(0)    收藏  举报