大家好,我是程序员柏风,AI 最全的 Vibecoding 学习地图 http://coderoadmap.cn 作者。
响应式基础
这一课你将能做到
- 正确使用
ref与reactive,并知道模板自动解包、script 需.value - 用
toRefs/ 解构陷阱解释「为什么解构丢响应式」 - 对照 React
useState:改数据的方式不同,但「UI 随状态变」一致
为什么要学
Vue 的自动更新建立在响应式系统上:它知道你读了哪些数据、改了哪些数据,从而精确更新。
不会 ref/reactive,就会出现「值改了页面不动」或「一解构全丢失」的常见卡点。
人话:ref 盒子装着值;reactive 把对象变成可追踪代理。
先建立图像
ref(0) → { value: 0 } 脚本用 .value,模板自动解包
reactive({ n: 0 }) → Proxy 对象,属性直接读写
解构 reactive 得到的普通变量 → 通常不再响应
| API | 适合 | 注意 |
|---|---|---|
| ref | 原始值、也可装箱对象 | 脚本 .value |
| reactive | 对象结构清晰时 | 别整体替换丢代理 |
| toRefs | 解构仍要响应 | 每个属性变 ref |
跟着做
步骤 1:ref 计数器
<script setup>
import { ref } from "vue";
const count = ref(0);
function inc() {
count.value++;
}
</script>
<template>
<button type="button" @click="inc">{{ count }}</button>
</template>
点按钮数字应增加。若写成 count++(没 .value)会不符合预期。
步骤 2:reactive 表单对象
<script setup>
import { reactive } from "vue";
const form = reactive({ title: "", level: "beginner" });
</script>
<template>
<input v-model="form.title" placeholder="课名" />
<p>{{ form.title }} · {{ form.level }}</p>
</template>
输入时应即时反映。v-model 下一课/表单场景常用——此处体验双向绑定。
步骤 3:解构陷阱
<script setup>
import { reactive } from "vue";
const form = reactive({ title: "SQL" });
// 错误示范:
const { title } = form; // title 是普通字符串快照
</script>
改 form.title,若模板绑的是已解构的 title,往往不更新。改用:
import { reactive, toRefs } from "vue";
const form = reactive({ title: "SQL" });
const { title } = toRefs(form); // title 是 ref
步骤 4:替换整个 reactive 对象?
let state = reactive({ n: 1 });
// 不推荐:state = reactive({ n: 2 }) 若别处仍握着旧引用会脱节
state.n = 2; // 改属性
需要「整对象可换」时,更常 const state = ref({ n: 1 }); state.value = { n: 2 }。
步骤 5:对照 React
| 任务 | Vue | React |
|---|---|---|
| 数字状态 | ref(0) / count.value++ | useState / setCount |
| 对象字段 | reactive 或 ref | 不可变更新 setState({...}) |
Vue 允许直接改属性;React 强调新引用。两边都不要「偷偷改数据却让框架不知情」。
步骤 6:故意写错再修好
先在 script 写 count = 1 覆盖 ref,观察按钮失灵;再改回 count.value = 1。
把失败现象记进笔记——比只背条文牢。
讲清楚要点
- 模板解包 ref,脚本不解包:分场景记。
- reactive 仅对象(含数组):原始值用 ref。
- 数组变更:
push/splice等会触发;注意不要切断引用。 shallowRef/shallowReactive:进阶性能优化,入门先用深响应。- 调试:Vue DevTools 可看组件状态,比 console 瞎打舒服。
- 与本站 React 对照学习:概念迁移,不要求混用在同一文件。
你可能会懵的地方
-
为什么官方又推 ref 又推 reactive?
团队风格不一;统一「顶层用 ref,大表单 reactive」也可。关键一致性。 -
ref装对象还要.value.x?
是。模板仍自动解包到对象。 -
异步里改状态页面不更新?
多数会更新;若自己接了非响应数据源,需先放进 ref。 -
markRaw?
跳过代理;入门少用。 -
和 Pinia 的关系?
store 内部同样建立在响应式上;先把组件内状态搞懂。
错法对照
| 错法 | 问题 | 正解 |
|---|---|---|
script 忘 .value | 页面不更新或类型错 | 读写加 .value |
| 解构 reactive | 丢响应 | toRefs 或用 form.x |
| 用普通变量当状态 | 改了不渲染 | ref/reactive |
| 覆盖整个 reactive 变量 | 引用断裂 | 改属性或改用 ref |
| 把 props 当可写状态 | 单向数据流破坏 | 本地 ref 或 emit |
| 与 React 不可变更新硬套乱改 | 两套习惯打架 | 按框架惯例写 |
自测三问
- 模板里写
{{ count }}为什么不用.value? - 何时优先
ref,何时reactive? - 解构
reactive对象后怎样保持响应?
小结一句话
响应式让数据变更自动驱动视图;分清 ref 的 .value、reactive 的代理与解构陷阱。
动手加深
把本课「跟着做」再跑一遍,但这次故意先写出错法表里的一种写法,观察报错或错误现象 30 秒,再改回正解。
用自己的话补三条笔记:① 我最容易踩的坑;② 成功时屏幕/结果长什么样;③ 本课与上一课的衔接点。写不出来就重做步骤,不要只标完成。
步骤 7:数组方法是否触发更新
对
ef([]):push 一条应更新;若你做了 list = [](丢掉 ref)再 push,模板会失灵。
刻意练一次「错误赋值 vs list.value.push」,把对比写进错法笔记。
官方延伸
- 响应式基础
- 下一课:组件与 Props