Vue3 Hooks 实现原理与源码解析
一、概述
Vue 3 的 Composition API(组合式 API)是通过一系列 Hook 函数实现的,这些 Hook 让我们能够以函数的方式组织组件逻辑。与 React Hooks 不同,Vue 3 的 Hook 基于响应式系统实现,不依赖调用顺序。[1]
核心特点:
- 基于 Proxy 的响应式系统
- 不依赖调用顺序(可以在条件语句中使用)
- 通过依赖收集实现自动更新
- 与组件实例生命周期紧密结合
二、响应式 Hook 原理
ref() 实现原理
ref() 是 Vue 3 最基础的响应式 API,用于创建一个响应式引用。
源码简化实现:
核心机制:
- 依赖收集(track):当在 effect 或组件渲染函数中访问
ref.value时,会调用trackRefValue()收集依赖 - 触发更新(trigger):当修改
ref.value时,会调用triggerRefValue()触发所有依赖的重新执行
reactive() 实现原理
reactive() 基于 Proxy 实现对象的深层响应式。
源码简化实现:
Proxy handlers 实现:
三、生命周期 Hook 原理
Vue 3 的生命周期 Hook(如 onMounted、onUpdated 等)通过在组件实例上注册回调函数实现。[1]
onMounted() 实现
核心注册函数:
执行时机:
生命周期钩子会在组件渲染过程的特定阶段被调用:
四、computed() 实现原理
computed() 创建一个惰性求值的计算属性,只有在依赖变化时才重新计算。
源码实现:
工作流程:
Loading diagram...
五、watch() 和 watchEffect() 原理
watchEffect() 实现
watch() 实现
核心实现 doWatch():
六、自定义 Hook
Vue 3 鼓励将可复用逻辑封装为自定义 Hook(通常以 use 开头命名)。
示例:useMousePosition
使用方式:
<template>
<div>鼠标位置: x , y </div>
</template>
<script setup>
import { useMousePosition } from './composables/useMousePosition'
const { x, y } = useMousePosition()
</script>示例:useAsyncData
七、核心依赖收集与触发机制
ReactiveEffect 类
track 和 trigger
八、总结
Vue 3 Hook 核心机制:
- 响应式基础:基于 Proxy 和 Reflect 实现数据劫持
- 依赖收集:通过
track()在访问数据时收集 effect - 触发更新:通过
trigger()在数据变化时通知所有依赖的 effect - 生命周期:通过
injectHook()在组件实例上注册回调 - 计算属性:通过脏检查实现缓存和惰性求值
- 侦听器:通过 ReactiveEffect 和调度器实现灵活的监听策略
与 React Hooks 的区别:
| 特性 | Vue 3 Hooks | React Hooks |
| 调用位置 | setup() 函数中 | 函数组件顶层 |
| 调用顺序 | 不依赖顺序,可在条件语句中 | 严格依赖顺序 |
| 响应式 | 基于 Proxy 自动追踪 | 需要手动声明依赖 |
| 更新机制 | 精确更新变化的部分 | 重新执行整个组件函数 |
| 性能 | 更细粒度的更新 | 依赖虚拟 DOM diff |