本节摘要:Vue 的响应式系统靠"数据被读取时记录依赖、数据变化时通知依赖"来工作。ref 包装基础值,reactive 包装对象,依赖追踪让"改数据界面自动变"落地。理解这套原理,你才能摸到头哪些写法会失效、哪些写法高效。
本节阅读目标
阅读完本节,你应当能够:
这是第 2.3 节思想的 Vue 实现。Vue 把数据包成响应式对象:当你读取它,它记下"谁在依赖我";当你改它,它掏出依赖表,通知那些依赖它的组件重新计算。于是 template 里引用过该数据的文本、指令,一起自动更新。
<script setup> import { ref, reactive } from 'vue'; const count = ref(0); const user = reactive({ name: '阿明', age: 28 }); </script> <template> <p>{{ count }} · {{ user.name }}</p> </template>
挑选要领:会整体替换的值用 ref;需要嵌套结构的对象用 reactive。两者都只在你"遵守规则访问"时才跟踪得到。
三个动作一条链:读取就登记、变化就通知、组件就重渲。把它画成流程比背文字直观得多。

摸清响应式的"边界",效率和安全一起提升。
| 失效场景 | 原因 | 修法 |
|---|---|---|
| 直接给普通变量赋值不更新 | 没被包成响应式 | 用 ref / reactive |
| 用下标新增对象属性不追 | 新增键未登记依赖 | 用 reactive 提前声明或整体替换 |
| 在模板外的普通函数改 ref 忘 .value | 访问不当 | 正确 .value |
一段"踩中又要修好"的代码把失效看个明白。下面这个搜索框,如果直接写:
let keyword = '';
然后希望在模板里 {{ keyword }} 跟着输入变,永远做不到——因为它根本没被包成响应式。正确做法是:
import { ref } from 'vue'; const keyword = ref('');
再看"新增键"那个坑:对 reactive 对象从来没出现过的属性,在运行期用 obj.newField = x 塞进去,Vue 是跟踪不到它的(因为新增键时并没有登记依赖)。稳妥办法是:一开始就在对象里占好位,或者整体替换。理解了这两处,就能明白排查方向永远先问一句"我走的是不是响应式通道"。
对大多数界面,ref / reactive 就够。响应式的价值是"少写手动同步",但要保的是"按规则用"。后续计算属性、侦听器都是站在这个响应式基座上做的二次抽象(4.5 节)。
把本节的机制收成两句不踩坑的经验,够日常支撑很久。第一句:ref 和 reactive 能互转、也能混用,但别在对象里嵌套 ref 之后又期待到处解包。reactive({ user: ref('阿明') }) 里那个 ref 在访问时会不会自动解包、赋值时要不要 .value,规则细碎且容易忘。更省心的选择是"浅层都用 ref,需要深结构再整体换成 reactive"——保持类型一致,读取时的心智负担最小。
第二句:当你发现"改成值、界面却不动",先别怀疑框架,先检查自己走的通道。凡是普通变量直接改的直接换 ref/reactive;凡是在异步回调里改响应式数据、却忘了它其实不是响应式的,也要回头包一层。绝大多数"不响应"不是机制坏了,而是你在响应式通道之外改了数据。记住这两条,比背下十条 API 更能守住实际项目的日常安全。
前面讲的是单个值的追踪,实际项目里还要面对一批对象的列表。Vue 的响应式并不会因为你放进一个数组就停手——把数组包进 reactive,列表项的新增、删除、更新同样会被追踪。体会这点,你的"列表数据一变、列表界面自动增删"就不再靠手动重建,而是天然生效:
<script setup> import { reactive } from 'vue'; const todos = reactive([ { id: 1, text: '起床' }, { id: 2, text: '写代码' }, ]); function addTodo(text) { todos.push({ id: Date.now(), text }); } </script> <template> <ul><li v-for="t in todos" :key="t.id">{{ t.text }}</li></ul> </template>
push 一次,界面列表就多一行,不用你手动操作 DOM 再插一个节点。这正是"数据驱动"在 Vue 复含量级上的兑现:维护数据,界面自会跟。要注意的是这里的更新仍要遵守前面"尽量整体替换或多用不可变手法"的偏好——频繁靠 push/splice 就地改,虽然响应式能感知,排查和回退反而麻烦。数据与界面同声共气,是响应式最令人畅快的时刻,也是"少写手动同步"这句目标的完整落地。
响应式让"数据驱动"自动运行。下一节看两个站在它上面的高级工具——计算属性与侦听器,一个管派生值缓存,一个管副作用追变。