【vue面试】ref和reactive

这个问题问得非常到位,而且你已经隐约抓到本质了:

ref 和 reactive 并不是"多余的语法糖",而是 Vue 为了解决「数据如何被追踪、如何更新视图」这个核心问题而设计的两种不同数据模型。

我分 「问题 → 解决方案 → 为什么要分成 ref / reactive」 三层来讲,而不是直接讲 API 用法。

一、Vue 真正要解决的不是"存数据",而是这 3 件事

在 Vue 里,数据从来不是目的,目的永远是:

  1. 数据变了

  2. Vue 能"感知到变化"

  3. 只更新依赖这份数据的视图 / 计算 / 副作用

也就是说,Vue 关心的是:

👉 "这份数据被谁用过?现在变了,要不要重新算?"

这叫:响应式(Reactivity)

二、JS 原生变量有一个致命问题

let count = 0

count++

JS 本身有两个 Vue 完全搞不定的点:

• ❌ 普通变量 没有"被读取"的钩子

• ❌ 普通变量 没有"被修改"的拦截点

Vue 无法知道:

复制代码
•	谁用过 count?
•	count++ 之后该通知谁?

👉 所以 Vue 必须"包住"你的数据

三、Vue 的核心技术:Proxy / getter / setter

Vue 3 本质上做的是:

• 读的时候:记录「谁在用我」

• 写的时候:通知「用过我的人更新」

这就需要:

• 对 对象属性 拦截 → Proxy

• 对 单个值 也能拦截 → ❓(JS 原生没有)

这就是 ref 和 reactive 分裂的根源

四、reactive:解决「对象整体」的响应式问题

适用场景

👉 "我有一个对象 / 数组,我关心的是它里面的字段变化"

const state = reactive({

user: {

name: 'Tom',

age: 18

}

})

Vue 做了什么?

state.name ← 读 → 记录依赖

state.name = x ← 写 → 触发更新

特点

• ✅ 天然适合「对象 / 数组」

• ✅ 结构和原生 JS 非常像

• ❌ 不能直接用于基本类型

为什么?

reactive(1) // ❌ 没有"属性"可拦截

五、ref:解决「单个值」也要响应式的问题

这是 Vue 被 JS 限制后不得不做的设计

JS 没办法拦截:

count++

所以 Vue 只能变成:

count.value++

ref 本质是什么?

const count = ref(0)

// 内部等价于

{

value: 0

}

然后:

• get value → 收集依赖

• set value → 触发更新

特点

• ✅ 基本类型(number / string / boolean)

• ✅ 也可以包对象

• ❌ 需要 .value(这是 JS 限制,不是 Vue 喜欢)

六、那为什么不只留一个?(核心问题)

这是你真正问到的地方。

如果只有 reactive

const count = reactive({ value: 0 })

问题:

• 写法丑

• 和 JS 直觉严重不符

• 模板里也很别扭

如果只有 ref

const state = ref({

user: { name: 'Tom' }

})

问题:

• 每一层都 .value

• 对象操作非常反人类

• 结构表达能力差

七、所以 Vue 设计成「两条路」

需求 方案

一个值(状态位、计数、开关) ref

一组有关联的数据 reactive

这不是功能重复,而是:

"对不同数据形态,提供最符合人类直觉的建模方式"

八、它们解决的"真正问题"一句话总结

ref 和 reactive 解决的不是"怎么存数据",而是:

在 JS 语言限制下,如何让 Vue 精确追踪「谁用过什么数据」,并在数据变化时最小代价地更新视图。

九、从"使用者视角"的判断标准(非常实用)

你在写代码时,可以用这 3 个判断:

  1. 是不是一个"独立状态"

👉 ref

  1. 是不是一组有结构的数据

👉 reactive

  1. 是否会被解构 / 传来传去

👉 ref(稳定)

十、一句你现在阶段最该记住的话

Vue 的响应式不是"数据结构",而是"数据与依赖之间的契约"。

ref 和 reactive 只是两种不同的"契约形式"。

如果你愿意,下一步我可以直接从 Vue 源码视角(track / trigger)给你画一条"数据 → 视图更新"的完整链路,或者对比 React useState 从"为什么完全不一样"来讲。

相关推荐
无羡仙9 分钟前
从零构建 Vue 弹窗组件
前端·vue.js
源心锁1 小时前
👋 手搓 gzip 实现的文件分块压缩上传
前端·javascript
源心锁2 小时前
丧心病狂!在浏览器全天候记录用户行为排障
前端·架构
GIS之路2 小时前
GDAL 实现投影转换
前端
phltxy2 小时前
从零入门JavaScript:基础语法全解析
开发语言·javascript
烛阴2 小时前
从“无”到“有”:手动实现一个 3D 渲染循环全过程
前端·webgl·three.js
BD_Marathon2 小时前
SpringBoot——辅助功能之切换web服务器
服务器·前端·spring boot
Kagol2 小时前
JavaScript 中的 sort 排序问题
前端·javascript
eason_fan3 小时前
Service Worker 缓存请求:前端性能优化的进阶利器
前端·性能优化
光影少年3 小时前
rn如何和原生进行通信,是单线程还是多线程,通信方式都有哪些
前端·react native·react.js·taro