Vue3 effect vs react hooks
- 先给结论:
- Vue3:以 effect 为中心的「依赖驱动」
- React:以 render + Hooks 为中心的「重执行驱动」
# 一、一句话对比(先立心智)
| 维度 | Vue3 | React |
|---|---|---|
| 核心单位 | effect(fn) | render(Component) |
| 更新模型 | 精确依赖触发 | 整函数重跑 |
| 响应式粒度 | 属性级 | 组件级 |
| 副作用调度 | scheduler | Scheduler + Fiber |
| 数据流 | pull(谁用谁收集) | push(setState 推) |
# 二、Vue3 effect
# 1️⃣ effect 的本质
effect(() => {
console.log(state.count)
})
1
2
3
2
3
发生了什么:
effect(fn)入栈(activeEffect)state.count→ gettertrack(target, key)- 建立 key → effect 的映射
state.count
↓
Set(effect)
1
2
3
2
3
# 2️⃣ 触发更新
state.count++
1
- setter
trigger(target, 'count')- 精确找到依赖 effect
- 执行 or scheduler(effect)
👉 不会影响没用到 count 的 effect
# 3️⃣ Vue effect 的核心优势
- 依赖自动收集
- 粒度极细
- effect ≠ render
- computed / watch 本质都是 effect
# 三、React Hooks:彻底不同的思路
# 1️⃣ React 的核心不是 Hook,是 render
function App() {
const [count, setCount] = useState(0)
return <div>{count}</div>
}
1
2
3
4
2
3
4
⚠️ 重点:
组件函数本身 = render effect
# 2️⃣ setState 发生了什么
setCount(1)
1
- 创建 update
- 进入 Fiber updateQueue
- 调度 Scheduler
- 重新执行整个组件函数
render(App)
├─ useState
├─ useEffect
├─ JSX
1
2
3
4
2
3
4
👉 React 不知道你用没用 count 👉 它选择:我全跑一遍
# 3️⃣ Hooks 的本质
# Hooks ≠ 响应式
useState
useEffect
useMemo
1
2
3
2
3
本质是:
hook[i]
1
- 靠 调用顺序
- 靠 Fiber.memoizedState
- 每次 render 顺序必须一致
# 四、依赖对比:自动 vs 手动(最本质差异)
# Vue computed
computed(() => a.value + b.value)
1
- getter 中自动 track
- a / b 改 → 触发
# React useMemo
useMemo(() => a + b, [a, b])
1
- 你手写依赖
- 写少了 = bug
- 写多了 = 性能问题
🧠 React 把控制权交给你
# 五、effect vs useEffect(名字相似,语义完全不同)
Vue effect | React useEffect | |
|---|---|---|
| 定位 | 响应式核心 | 副作用 Hook |
| 是否 render | ❌ | ❌ |
| 是否依赖收集 | ✅ 自动 | ❌ 手动 |
| 调度时机 | 同步 / 微任务 | commit 后 |
| 是否可嵌套 | ✅ | ❌ |
⚠️ 千万别把 useEffect 当 watch
# 六、调度模型对比(scheduler)
# Vue
setter → trigger → scheduler → jobQueue
1
- effect 有 scheduler
- computed 是 lazy
- watch 可 flush sync / post
# React
setState
→ Scheduler(lane)
→ render(可中断)
→ commit(不可中断)
1
2
3
4
2
3
4
- render 可被打断
- commit 一定完成
- 并发来自 Fiber
# 七、为什么 React 能并发,Vue 不强调?
# Vue 的问题
- effect 粒度太细
- 依赖关系复杂
- 中断成本高
# React 的选择
- 粗粒度 render
- render 可重跑
- 天然支持中断 / 重试
👉 这是 Fiber 的设计前提
# 八、闭包问题:Vue 几乎没有,React 到处都是
# React 闭包陷阱
useEffect(() => {
setInterval(() => {
console.log(count)
}, 1000)
}, [])
1
2
3
4
5
2
3
4
5
👉 count 永远是初始值
# Vue 不会
watchEffect(() => {
console.log(count.value)
})
1
2
3
2
3
# 九、源码级一一对应(核心对照)
| Vue3 | React |
|---|---|
effect | renderWithHooks |
track | 手写 deps |
trigger | dispatchAction |
| scheduler | Scheduler |
| Dep Map | Fiber.memoizedState |
# 十、总结
- Vue3 是“响应式引擎 + 编译器”
- React 是“可重跑的纯函数 + 调度系统”
不是谁更先进,是取舍不同。
上次更新: 2026/01/09, 03:15:08