[Vue源码系列-3]vue3依赖收集实现原理

[Vue源码系列-3]vue3依赖收集实现原理
最新回答
凭栏听雨

2026-10-27 08:29:50

Vue3 依赖收集实现原理

Vue3 的响应式系统通过依赖收集(dependency tracking)和触发更新(trigger updates)两个核心机制,实现了对数据的自动追踪和更新。以下是 Vue3 依赖收集实现原理的详细解析:

一、依赖收集的核心组件
  1. effect 函数

    作用:用于注册副作用函数,当响应式数据变化时,自动执行这些函数。

    实现:通过 createReactiveEffect 函数创建,并存储在 effectStack 中以避免重复收集。

    执行时机:默认情况下,effect 函数会立即执行一次,以收集初始依赖。

  2. track 函数

    作用:在响应式数据的 getter 中调用,用于收集当前正在执行的 effect 函数作为依赖。

    实现:通过 WeakMap 和 Map 数据结构,将目标对象、属性键和对应的 effect 集合关联起来。

    条件:只有在 activeEffect(当前正在执行的 effect)存在时,才会余清进行依赖收集。

  3. trigger 函数

    作用:在响应式数据的 setter 中调用,用于触发与属性相关的所有 effect 函数。

    实现:通过查找 WeakMap 中存储的依赖关系,获取与属性相竖羡前关的 effect 集合,并执行这些函数。

    去重:使用 Set 数据结构对 effect 进行去重,确保每个 effect 只执行一次。

二、依赖收集的实现流程
  1. 初始化响应式数据

    使用 reactive 函数将普通对象转换为响应式对象。

    在响应式对象的属性访问时(getter),通过代理(Proxy)拦截并调用 createGetter 函数。

  2. 执行 effect 函数

    调用 effect 函数注册副作用。

    effect 函数执行时,会将其自身推入 effectStack 中,并设置为 activeEffect。

    在 effect 函数内部访问响应式数据时,会触发 getter,进而调用 track 函数收集依赖。

  3. 收集依赖

    track 函数根据当前 activeEffect 和访问的属性键,在 WeakMap 和 Map 中建立依赖关系。

    如果该属性之前未收集过依赖,则创建一个新的 Set 存储当前的 effect。

    如果已收集过依赖,则检查 effect 是否已存在,避免重复收集。

  4. 触发更新

    当响应式数据变化时(setter),调用 trigger 函数。

    trigger 函数根据变化的属性键和类型,查找相关的 effect 集合。

    遍历 effect 集合,执行每个 effect 函数,实现视图更新。

三、解决特定问题
  1. 函数栈执行存在的问题

    嵌套 effect:在 effect 函数内部再调用 effect 函数时,需要确保内层 effect 不会重复收集外层 effect 的依赖。

    解决方案:通过 effectStack 记录当前正在派或执行的 effect,并在 createReactiveEffect 函数中检查 effect 是否已存在于 effectStack 中,以避免重复收集。

  2. 防止重复收集

    重复执行:在响应式数据变化时,需要确保每个 effect 只执行一次。

    解决方案:在 trigger 函数中使用 Set 数据结构对 effect 进行去重处理。

四、总结

Vue3 的依赖收集机制通过 effect、track 和 trigger 三个核心函数,实现了对响应式数据的自动追踪和更新。通过 WeakMap 和 Map 数据结构建立依赖关系,并使用 Set 数据结构进行去重处理,确保了依赖收集的准确性和高效性。同时,通过 effectStack 解决了嵌套 effect 导致的重复收集问题。