Vue3 ref 和 reactive 怎么选?


一、两者是什么

  • ref:把任意类型string / number / object / DOM…)包成响应式对象,通过 .value 读写;模板里自动解包,不用写 .value
  • reactive:专门给对象 / 数组用的深层响应式包装,直接访问属性即可,没有 .value
import { ref, reactive } from "vue";

const count = ref(0);
count.value++; // 脚本里要 .value
console.log(count.value); // 1

const state = reactive({ name: "Tom", age: 18 });
state.age++; // 直接改属性

二、核心区别

维度 ref reactive
支持类型 任意类型 仅对象 / 数组
访问方式 .value 直接 .属性
模板解包 自动解包 不需要解包
解构 解构后仍是响应(返回的是 ref) 解构会丢失响应
TS 推导 自动推导内部类型 类型来自原对象
替换整个对象 xxx.value = newObj 仍响应 整体替换会丢响应

三、选型场景

  • 用 ref: 基本类型(计数、开关、ID)、表单里的单值字段、DOM ref,以及组合式函数的返回值
  • 用 reactive: 一个多字段的表单对象复杂状态对象(user、settings),用属性访问更自然。
  • 组合式函数(composable)一律返回 ref: 调用方解构时不会丢失响应。
// composable 返回 ref,调用方解构也安全
export function useCounter() {
    const count = ref(0);
    const inc = () => count.value++;
    return { count, inc }; // 解构 { count, inc } 仍是响应的
}

四、常见坑

  1. reactive 解构丢失响应 → 用 toRefs
const state = reactive({ x: 1, y: 2 });
const { x, y } = toRefs(state); // 现在是 ref,仍响应

不解构直接 const { x } = state 会拿到普通数字,后续改 state.x 视图不更新。

  1. ref 放进 reactive 会自动解包: reactive({ count: ref(0) }) 访问时 obj.count 已是数字,不用 .value

  2. reactive 不能直接整体替换:

let state = reactive({ a: 1 });
state = { a: 2 }; // 变成普通对象,失去响应
// 用 Object.assign(state, { a: 2 }) 或改用 ref 包对象
  1. ref 数组 / Map 没坑;reactive 的数组整体替换也要注意: arr = newArr 会丢响应,改内容(push / splice)才安全。

五、相关阅读

  • 《Vue3新特性及和Vue2的部分差异性(持续更新汇中)》(/2023/04/12043.html) —— Vue3 新特性全貌与 Vue2 差异
  • 《详解Vue3中shallowRef和shallowReactive的使用》(/2026/05/26164.html) —— 浅响应式场景与性能优化

文章作者: 弈心
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 弈心 !
评论
  目录