Vue vs React 依赖收集机制对比
Vue3 自动依赖追踪 vs React 显式依赖声明的机制对比。
#type / synthesis
#status / growing
#tech / dev / frame
#resource / react
#resource / vue3
[!info] related notes
- 所属 MOC: Vue MOC, React MOC
- 前置概念: Vue3 Proxy 响应式原理, React useState 内部原理, React useEffect 内部原理
- 并列概念: Vue vs React 触发更新对比, Vue vs React 状态模型核心差异
- 关系笔记: React 状态模型 vs Vue3 响应式模型
Vue vs React 依赖收集机制对比
主题范围
本篇聚焦 Vue3 和 React 在”依赖如何被追踪/声明”这一维度上的核心差异。
一句话结论
- Vue3:自动追踪依赖,读到什么字段,就自动收集什么为依赖
- React:显式声明依赖,开发者需要在依赖数组里手动列出
Vue3:自动依赖追踪
运行时代理 + 自动收集
Vue3 在 effect 执行时,通过 Proxy 拦截读取操作,自动把被读取的响应式属性记录为依赖:
const state = reactive({ count: 0, name: 'Tom' })
effect(() => {
console.log(state.count) // 读取 count,自动收集依赖
})
依赖存储结构
targetMap: WeakMap {
state => Map {
'count' => Set([effect1]),
'name' => Set([effect2])
}
}
优势
- 开发者体验好:不用手动列依赖
- 自动精确:只有真正读取的字段才会触发更新
- 自动移除:依赖的字段不再被读取时,自动解除关系
React:显式依赖声明
依赖数组模式
React 通过 useEffect 的第二个参数声明依赖:
useEffect(() => {
console.log(count) // 这里用了 count
}, [count]) // 手动声明依赖
依赖决定时机
- 组件重新渲染 → 检查依赖是否变化 → 决定是否执行 effect
- 依赖是”上一次渲染”的值,不是实时响应
依赖数组的问题
useEffect(() => {
const id = setInterval(() => {
console.log(count) // 这里用了 count
}, 1000)
return () => clearInterval(id)
}, [count]) // 如果 count 变化,effect 会重新执行
常见问题:
- 依赖写少了:闭包陷阱,读到旧值
- 依赖写多了:频繁执行,性能问题
- 依赖写错了:行为不符合预期
对比表
| 维度 | Vue3 | React |
|---|---|---|
| 依赖声明方式 | 自动追踪 | 手动依赖数组 |
| 粒度 | 字段级 | 组件级 |
| 依赖变化时 | 精确触发对应 effect | 整个 effect 重新执行 |
| 开发者工作 | 少(自动) | 多(手动) |
| 闭包问题 | 无 | 有(需注意) |
最短记忆方式
- Vue:读取时自动收集 → “谁读了我”
- React:渲染时检查依赖 → “谁变了”