Skip to content
  • Vue3:以 effect 为中心的「依赖驱动」
  • React:以 render + Hooks 为中心的「重执行驱动」

一、一句话对比(先立心智)

维度Vue3React
核心单位effect(fn)render(Component)
更新模型精确依赖触发整函数重跑
响应式粒度属性级组件级
副作用调度schedulerScheduler + Fiber
数据流pull(谁用谁收集)push(setState 推)

二、Vue3 effect

1️⃣ effect 的本质

ts
effect(() => {
  console.log(state.count)
})

发生了什么:

  1. effect(fn) 入栈(activeEffect)
  2. state.count → getter
  3. track(target, key)
  4. 建立 key → effect 的映射
txt
state.count

Set(effect)

2️⃣ 触发更新

ts
state.count++
  1. setter
  2. trigger(target, 'count')
  3. 精确找到依赖 effect
  4. 执行 or scheduler(effect)

👉 不会影响没用到 count 的 effect

3️⃣ Vue effect 的核心优势

  • 依赖自动收集
  • 粒度极细
  • effect ≠ render
  • computed / watch 本质都是 effect

三、React Hooks:彻底不同的思路

1️⃣ React 的核心不是 Hook,是 render

jsx
function App() {
  const [count, setCount] = useState(0)
  return <div>{count}</div>
}

⚠️ 重点:

组件函数本身 = render effect

2️⃣ setState 发生了什么

ts
setCount(1)
  1. 创建 update
  2. 进入 Fiber updateQueue
  3. 调度 Scheduler
  4. 重新执行整个组件函数
txt
render(App)
  ├─ useState
  ├─ useEffect
  ├─ JSX

👉 React 不知道你用没用 count 👉 它选择:我全跑一遍

3️⃣ Hooks 的本质

Hooks ≠ 响应式

ts
useState
useEffect
useMemo

本质是:

ts
hook[i]
  • 调用顺序
  • Fiber.memoizedState
  • 每次 render 顺序必须一致

四、依赖对比:自动 vs 手动(最本质差异)

Vue computed

ts
computed(() => a.value + b.value)
  • getter 中自动 track
  • a / b 改 → 触发

React useMemo

ts
useMemo(() => a + b, [a, b])
  • 你手写依赖
  • 写少了 = bug
  • 写多了 = 性能问题

🧠 React 把控制权交给你

五、effect vs useEffect(名字相似,语义完全不同)

Vue effectReact useEffect
定位响应式核心副作用 Hook
是否 render
是否依赖收集✅ 自动❌ 手动
调度时机同步 / 微任务commit 后
是否可嵌套

⚠️ 千万别把 useEffect 当 watch

六、调度模型对比(scheduler)

Vue

txt
setter → trigger → scheduler → jobQueue
  • effect 有 scheduler
  • computed 是 lazy
  • watch 可 flush sync / post

React

txt
setState
 → Scheduler(lane)
 → render(可中断)
 → commit(不可中断)
  • render 可被打断
  • commit 一定完成
  • 并发来自 Fiber

七、为什么 React 能并发,Vue 不强调?

Vue 的问题

  • effect 粒度太细
  • 依赖关系复杂
  • 中断成本高

React 的选择

  • 粗粒度 render
  • render 可重跑
  • 天然支持中断 / 重试

👉 这是 Fiber 的设计前提

八、闭包问题:Vue 几乎没有,React 到处都是

React 闭包陷阱

ts
useEffect(() => {
  setInterval(() => {
    console.log(count)
  }, 1000)
}, [])

👉 count 永远是初始值

Vue 不会

ts
watchEffect(() => {
  console.log(count.value)
})

九、源码级一一对应(核心对照)

Vue3React
effectrenderWithHooks
track手写 deps
triggerdispatchAction
schedulerScheduler
Dep MapFiber.memoizedState

十、总结

  • Vue3 是“响应式引擎 + 编译器”
  • React 是“可重跑的纯函数 + 调度系统”

不是谁更先进,是取舍不同。