2026-10-27 08:29:50
Vue3 依赖收集实现原理
Vue3 的响应式系统通过依赖收集(dependency tracking)和触发更新(trigger updates)两个核心机制,实现了对数据的自动追踪和更新。以下是 Vue3 依赖收集实现原理的详细解析:
一、依赖收集的核心组件effect 函数
作用:用于注册副作用函数,当响应式数据变化时,自动执行这些函数。
实现:通过 createReactiveEffect 函数创建,并存储在 effectStack 中以避免重复收集。
执行时机:默认情况下,effect 函数会立即执行一次,以收集初始依赖。
track 函数
作用:在响应式数据的 getter 中调用,用于收集当前正在执行的 effect 函数作为依赖。
实现:通过 WeakMap 和 Map 数据结构,将目标对象、属性键和对应的 effect 集合关联起来。
条件:只有在 activeEffect(当前正在执行的 effect)存在时,才会余清进行依赖收集。
trigger 函数
作用:在响应式数据的 setter 中调用,用于触发与属性相关的所有 effect 函数。
实现:通过查找 WeakMap 中存储的依赖关系,获取与属性相竖羡前关的 effect 集合,并执行这些函数。
去重:使用 Set 数据结构对 effect 进行去重,确保每个 effect 只执行一次。
初始化响应式数据
使用 reactive 函数将普通对象转换为响应式对象。
在响应式对象的属性访问时(getter),通过代理(Proxy)拦截并调用 createGetter 函数。
执行 effect 函数
调用 effect 函数注册副作用。
effect 函数执行时,会将其自身推入 effectStack 中,并设置为 activeEffect。
在 effect 函数内部访问响应式数据时,会触发 getter,进而调用 track 函数收集依赖。
收集依赖
track 函数根据当前 activeEffect 和访问的属性键,在 WeakMap 和 Map 中建立依赖关系。
如果该属性之前未收集过依赖,则创建一个新的 Set 存储当前的 effect。
如果已收集过依赖,则检查 effect 是否已存在,避免重复收集。
触发更新
当响应式数据变化时(setter),调用 trigger 函数。
trigger 函数根据变化的属性键和类型,查找相关的 effect 集合。
遍历 effect 集合,执行每个 effect 函数,实现视图更新。
函数栈执行存在的问题
嵌套 effect:在 effect 函数内部再调用 effect 函数时,需要确保内层 effect 不会重复收集外层 effect 的依赖。
解决方案:通过 effectStack 记录当前正在派或执行的 effect,并在 createReactiveEffect 函数中检查 effect 是否已存在于 effectStack 中,以避免重复收集。
防止重复收集
重复执行:在响应式数据变化时,需要确保每个 effect 只执行一次。
解决方案:在 trigger 函数中使用 Set 数据结构对 effect 进行去重处理。
Vue3 的依赖收集机制通过 effect、track 和 trigger 三个核心函数,实现了对响应式数据的自动追踪和更新。通过 WeakMap 和 Map 数据结构建立依赖关系,并使用 Set 数据结构进行去重处理,确保了依赖收集的准确性和高效性。同时,通过 effectStack 解决了嵌套 effect 导致的重复收集问题。