前端进阶之旅前端进阶之旅
  • 基础篇HTML/CSS/JS 打底
  • 进阶篇原理与工程化
  • 高频篇面试最常问的那批
  • 精选篇按模块收敛的总结
  • 手写篇常考代码手写实现
  • 面经篇真实面试问题复盘
  • AI 篇NEWAI 时代的前端考点
  • 历年面经NEW按年份追踪真实考点
  • 每日一题每天一道,攒手感
  • 专项自测100 题快速查漏
  • 小程序题库小程序专项刷题
  • 算法题库NEW在线编码即时判题
  • 知识卡片NEW碎片时间过考点
  • 面试题大全常见问题解析
  • AI 答疑NEW随时提问,即时解析
  • AI 模拟面试NEW模拟真实面试 + 报告
  • AI 定制路线NEW按你的简历现排
  • AI 知识地图NEW串起全站知识点
  • 原理篇React / Vue 源码拆解
  • HTTP从报文一路讲到 HTTPS
  • 浏览器渲染、事件循环、进程
  • 计算机基础Linux、网络、操作系统
  • 设计模式23 种模式怎么用
  • Node学习指南从环境搭建到服务端
  • NPM工作流script、依赖与发布
  • Docker容器化部署上手
  • Canvas图形与动画实战
  • 前端系统进阶学习大型项目工程化
  • 前端综合文章长期沉淀的实践文
  • 思维导图知识点全景图
  • 学习路线按图索骥不跑偏
  • AI 热点NEWAI 每日动态
  • 公众号动态公众号历史文章
  • 博客动态站长的技术博客
  • 开发者导航常用工具与文档站
  • 基础篇HTML/CSS/JS 打底
  • 进阶篇原理与工程化
  • 高频篇面试最常问的那批
  • 精选篇按模块收敛的总结
  • 手写篇常考代码手写实现
  • 面经篇真实面试问题复盘
  • AI 篇NEWAI 时代的前端考点
  • 历年面经NEW按年份追踪真实考点
  • 每日一题每天一道,攒手感
  • 专项自测100 题快速查漏
  • 小程序题库小程序专项刷题
  • 算法题库NEW在线编码即时判题
  • 知识卡片NEW碎片时间过考点
  • 面试题大全常见问题解析
  • AI 答疑NEW随时提问,即时解析
  • AI 模拟面试NEW模拟真实面试 + 报告
  • AI 定制路线NEW按你的简历现排
  • AI 知识地图NEW串起全站知识点
  • 原理篇React / Vue 源码拆解
  • HTTP从报文一路讲到 HTTPS
  • 浏览器渲染、事件循环、进程
  • 计算机基础Linux、网络、操作系统
  • 设计模式23 种模式怎么用
  • Node学习指南从环境搭建到服务端
  • NPM工作流script、依赖与发布
  • Docker容器化部署上手
  • Canvas图形与动画实战
  • 前端系统进阶学习大型项目工程化
  • 前端综合文章长期沉淀的实践文
  • 思维导图知识点全景图
  • 学习路线按图索骥不跑偏
  • AI 热点NEWAI 每日动态
  • 公众号动态公众号历史文章
  • 博客动态站长的技术博客
  • 开发者导航常用工具与文档站
首页程序员面试题库Vue ref 和 reactive 原始值区别
VuVue响应式原理

Vue 3 已经有 reactive,为什么还需要 ref?

reactive 代理对象的属性访问,ref 则用稳定的 value 入口承载一个可被追踪和替换的值。

前端进阶之旅 · 一题精讲更新于 2026.09.06
Vue#响应式原理
先看核心答案
理解线索

追踪入口与业务值不是同一个东西

  1. 对象代理reactive 通过代理对象的属性读取与修改建立联系
  2. 值容器ref 在 value 入口记录对内部值的读取与更新
  3. 调用边界传递容器或 getter 才能让接收方继续读取变化

模板里的自动解包是使用便利,不代表 JavaScript 中读取 ref 永远不需要 value。

核心回答

先记住这个答案

reactive 需要对象作为代理目标,不能直接把一个数字变量的赋值变成可追踪操作。ref 提供带 value 属性的容器,让读取与赋值经过 Vue 能追踪的入口,因此能表示数字、字符串等原始值,也能保存对象。它的意义不只是补上原始类型,还便于保留稳定的容器身份并整体替换内部值。选择时应看数据如何更新和传递,而不是简单规定对象只能用 reactive。

  • 原始变量赋值没有对象属性入口供代理追踪
  • ref 容器身份可保持稳定,value 可以整体替换
  • ref 也能保存对象,普通 ref 会进行深层响应式转换

为什么包一层对象有实际作用

假设分页状态是一个数字 page,普通赋值只改变当前变量绑定,并没有一个可被 Vue 拦截的属性写入。使用 ref 后,修改 page.value 会经过响应式入口;依赖这个值的计算就能知道输入发生变化。容器并非为了多写一个属性,而是为原始值建立可追踪的读写位置。

使用 reactive({ page: 1 }) 也能表达分页状态,因为这里被代理的是对象,page 是它的属性。两种方式都可以成立,区别在于你希望把分页作为独立值传递,还是作为一组状态中的字段维护。没有必要为证明某种 API 更先进而强行改写清楚的数据模型。

对象整体替换时 ref 提供稳定入口

搜索结果可能在每次请求后整体替换为一个新对象。若其它逻辑持有同一个 result ref,它们下一次读取 result.value 时就能得到新对象。普通 ref 中的对象会被转换成深层响应式代理,因此内部字段变化也可能被追踪;需要保留外部对象原样身份时再考虑 shallowRef 等明确边界。

对 let state = reactive(...) 重新赋一个新代理,只是替换了那个局部变量;已经拿到旧代理的组合函数并不会自动改成持有新代理。可以维持原代理并按业务规则更新字段,也可以从一开始通过 ref 提供可替换对象的稳定入口,选择应与数据生命周期一致。

传递 ref 与传递当前值的效果不同

把 page.value 作为参数传给普通函数,传出去的是这次读取到的数字,不会自动附带后续变化关系。需要接收方持续读取时,可以传 ref、getter 或包含该字段的响应式对象,并让接收方在响应式计算中真正读取它。接口契约应说明接收静态值还是动态来源。

模板会对某些位置的 ref 自动解包,所以展示时看起来可以直接写 page,但脚本中的对象、数组和集合有各自规则。不要因为一个模板表达式省略了 value,就在 JavaScript 计算中把 ref 对象当成数字相加。排查类型与更新问题时,先确认拿到的是容器还是内部值。

回答前,多想一步

容易答错的地方

ref 只能保存字符串、数字和布尔值
ref 可以保存对象,并且普通 ref 会对对象进行深层响应式转换。需要浅层持有外部实例时,应明确选择对应 API,而不是用“对象不能放 ref”解释行为。
把 ref.value 传出去就会一直保持最新
传出原始值时只是传递当前快照。持续响应需要接收方保留可读取的来源,并在响应式上下文内访问,不能期待值本身带有隐式订阅。
试着用自己的话回答

面试官还会怎么问?

ref 和 reactive 可以混合使用吗?

可以,但要清楚属性自动解包与容器身份的边界。混合不是问题,接口让调用方猜测当前需要读 value 还是直接读字段,才容易造成维护成本。

为什么 const 声明的 ref 仍能更新?

const 固定的是变量绑定到哪个 ref 对象,并不冻结这个对象的 value。修改 value 与把变量重新绑定到另一个 ref,是不同的操作。

什么时候考虑 shallowRef?

需要只在整体替换时触发更新,或希望保留第三方实例、不可变数据等内部结构时可以评估。浅层持有不会自动追踪任意深层修改,调用方必须理解这个约定。

从一道题,走向一组知识

把知识连起来

响应式原理

Vue reactive 多次代理同一对象会返回同一个值吗,为什么不等于原对象?

使用对象代理时,还要分清原始对象、代理对象与整体替换的身份关系。

响应式原理

Vue toRef 和 toRefs 怎么选择,和 ref(state.field) 有什么区别?

将对象字段传给组合函数时,可以进一步选择保持字段连接的引用。

参考资料

  • Reactivity Fundamentals
  • Reactivity API: Core

示例用于理解所注明的运行环境与边界;延伸学习可结合原文中的更多案例。

本题目录
  1. 先记住这个答案
  2. 为什么包一层对象有实际作用
  3. 对象整体替换时 ref 提供稳定入口
  4. 传递 ref 与传递当前值的效果不同
  5. 容易答错的地方
  6. 面试官还会怎么问
  7. 把知识连起来
读懂,再试着讲出来

先看核心答案,再读代码。最后展开追问,检查自己有没有遗漏边界。

试着回答追问
浏览全部面试题理解原理,也关注真实的使用场景。回到顶部 ↑