Glittering's blog Glittering's blog
Home
  • 学习手册

    • 《JavaScript教程》
    • 《TypeScript教程》
    • 《Git》
    • 《Vite》
    • 《Vue3》
    • 《React18》
    • 《CSS》
    • 《Tailwind CSS》
    • 《ES6 教程》
    • 《TypeScript 从零实现 axios》
  • 技术文档
  • 算法
  • 工作总结
  • 实用技巧
  • collect
About
  • Classification
  • Label
GitHub (opens new window)

Glitz Ma

前端开发工程师
Home
  • 学习手册

    • 《JavaScript教程》
    • 《TypeScript教程》
    • 《Git》
    • 《Vite》
    • 《Vue3》
    • 《React18》
    • 《CSS》
    • 《Tailwind CSS》
    • 《ES6 教程》
    • 《TypeScript 从零实现 axios》
  • 技术文档
  • 算法
  • 工作总结
  • 实用技巧
  • collect
About
  • Classification
  • Label
GitHub (opens new window)
  • react基础

  • react原理

    • Vue3 effect vs react hooks
      • 1️⃣ effect 的本质
      • 2️⃣ 触发更新
      • 3️⃣ Vue effect 的核心优势
      • 1️⃣ React 的核心不是 Hook,是 render
      • 2️⃣ setState 发生了什么
      • 3️⃣ Hooks 的本质
        • Hooks ≠ 响应式
      • Vue computed
      • React useMemo
      • Vue
      • React
        • Vue 的问题
        • React 的选择
      • React 闭包陷阱
        • Vue 不会
    • Fiber是什么
    • renderWithHooks是怎么挂到Fiber
    • mount/update为什么能切换
    • React 更新系统的“回路闭合点”
    • 为什么hooks不能写在条件里
    • 为啥hooks要用全局变量(而不是参数传递)
  • react全家桶

  • 《React18》学习笔记
  • react原理
mamingjuan
2025-09-08
目录

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

发生了什么:

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

# 2️⃣ 触发更新

state.count++
1
  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

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

⚠️ 重点:

组件函数本身 = render effect


# 2️⃣ setState 发生了什么

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

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


# 3️⃣ Hooks 的本质

# Hooks ≠ 响应式

useState
useEffect
useMemo
1
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
  • 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

👉 count 永远是初始值

# Vue 不会

watchEffect(() => {
  console.log(count.value)
})
1
2
3

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

Vue3 React
effect renderWithHooks
track 手写 deps
trigger dispatchAction
scheduler Scheduler
Dep Map Fiber.memoizedState

# 十、总结

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

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

上次更新: 2026/01/09, 03:15:08
class和hooks选哪个好
Fiber是什么

← class和hooks选哪个好 Fiber是什么→

Copyright © 2015-2026 Glitz Ma
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式