关键在数据类型与变更方式:基础类型必须用ref;对象/数组结构稳定时优先reactive;需整体替换时ref更安全;解构需toRefs;DOM引用、特殊对象、性能敏感场景各有最优选。

选 reactive 还是 ref,关键不在“哪个更好”,而在于“数据怎么变、谁在用、怎么传”。用错一个,轻则响应失效、调试抓狂,重则性能掉档、内存泄漏。
看数据类型和变更方式
基础类型(数字、字符串、布尔)必须用 ref——reactive 根本不接受。比如计数器、开关状态、搜索关键词,直接 const searchKey = ref('') 最干净。
对象或数组结构稳定、属性频繁修改(如表单、配置项、loading/error/data 状态包),优先用 reactive。例如:const form = reactive({ username: '', password: '' }),改字段不用写 .value,语义也更贴近“一个整体状态”。
需要整个替换对象(比如接口返回新用户数据,直接覆盖旧对象),ref 更自然:user.value = newUser 一行搞定;而 reactive 若写 user = newUser,会彻底丢失响应性。
看使用位置和传递需求
从 setup 返回给模板时,如果要解构(如 const { name, age } = user),必须用 toRefs(user) 或全用 ref。直接 return reactive 对象再解构,响应性就断了。
作为组合式函数(composable)的返回值,若只暴露一个核心状态(比如 useCounter() 返回一个 count),用 ref 更清晰——调用方拿到的就是一个可直接 watch、v-model、传递的“原子单位”。
若返回一组强关联的状态(如分页信息:page, pageSize, total),用 reactive 包成一个对象,再配合 toRefs 暴露,既保持内聚,又避免每个都写 .value。
看与 DOM 或工具的交互场景
ref 是唯一能绑定 DOM 元素或组件实例的选项。比如 const inputRef = ref(null) + <input ref="inputRef">,这是 ref 的专属语义,reactive 做不到。
涉及第三方库集成(如 Chart.js、Map 实例)、手动 focus/scroll/播放控制,一律用 ref。它本质是“持有引用的容器”,不是为响应式设计,但恰好满足这类需求。
遇到 Map、Set、Date、RegExp 等非普通对象,reactive 无法代理其内部变化,此时要么用 ref 包一层,要么用 shallowRef + 手动触发更新,别硬套 reactive。
看性能与规模敏感操作
万级列表渲染时,测试显示:reactive 初始渲染略快(约15%),但高频局部更新(如单条高亮、实时筛选)时 ref 更稳、卡顿更少。尤其做关键词过滤,ref 方案帧率更平滑。
内存方面,reactive 因 Proxy 开销,比同等 ref 高出 10%-15%。若页面存在大量独立小状态(如每行一个开关),用多个 ref 反而比一个大 reactive 对象更轻量。
watch 场景也要注意:监听 reactive 对象默认深度,无需 { deep: true };监听 ref 的对象值,则必须加 deep: true,否则嵌套属性变化不会触发——这个细节极易漏掉。


















