2025.09.18

模块解耦:reactivity 架构的逻辑拆分

🏛️ 架构目标:高复用与单一职责

为了提升系统性能和遵循单一职责原则,reactivity 模块的实现采取了高度解耦的架构。核心思路是将 Proxy 的拦截逻辑(get/ set)从创建函数中抽离出来,形成一个独立的、可共享的 handlers 模块。

设计优势:

  • 性能提升: 所有代理实例共享同一份 mutableHandlers 对象, 避免每次创建代理时都重复创建和初始化 handlers 对象的开销
  • 高复用性: 不同的响应式 API(如 reactive shallowReactive) 可以轻松复用或组合这些基础 handlers

📦 模块职责划分

reactivity 核心功能被清晰地划分为三个主要模块:

模块核心职责关键功能
reactive.ts代理创建与身份识别reactive 函数、缓存机制(reactiveMap)、身份验证(isReactive)
baseHandlers.tsProxy 拦截拦截 get/set、实现深度代理、ref 自动解包、值变化对比
dep.ts依赖收集与派发依赖存储(targetMap、依赖收集(track)、派发更新(trigger)
  1. 核心拦截器: baseHandlers.ts
    get 拦截: 收集、解包、递归代理
    export const mutableHandlers: ProxyHandler<any> = {
      get(target, key, receiver) {
        track(target, key) // 📌 1. 依赖收集
    
        const res = Reflect.get(target, key, receiver)
        if (isRef(res)) {
          return res.value // 📌 2. Ref 自动解包
        }
    
        if (isObject(res)) {
          return reactive(res) // 📌 3. 深度代理 (惰性递归)
        }
    
        return res
      }
    // ...
    }
    

    set拦截: 值同步与值变化对比
    export const mutableHandlers: ProxyHandler<any> = {
      // ...
      set(target, key, newValue, receiver) {
        const oldValue = target[key]
    
        // 📌 1. Ref 同步修改:如果旧值是 ref,且新值不是 ref,直接修改 ref.value
        if (isRef(oldValue) && !isRef(newValue)) {
          oldValue.value = newValue
          return true
        }
    
        const res = Reflect.set(target, key, newValue, receiver)
        // 📌 2.值真正变化才触发更新
        if (hasChanged(newValue, oldValue)) {
          trigger(target, key)
        }
        return res
      }
    }
    
  2. 依赖管理中心: dep.ts
    该模块专注于维护 targetkeyeffect 之间的三层映射关系,确保依赖追踪的精准性。
    结构和职责
    • targetMap: 全局 WeakMap, 存储 target -> depsMap 的映射
    • Dep Class: 通过双向链表(subs), 存储单个属性的所有依赖
    • track: 确保 activeSub 被链接到 target[key] 对于的 Dep
    • trigger: 通过 targetMap 找到目标 Dep 并调用 propagate 派发更新
    // dep.ts 摘要
    export const targetMap: WeakMap<Target, any> = new WeakMap<Target, any>()
    
    export function track(target: object, key: unknown) {
      // ... 查找 depsMap, Dep, 并调用 link(dep, activeSub)
    }
    
    export function trigger(target: object, key: unknown) {
      // ... 通过 targetMap 查找 Dep, 并调用 propagate(dep.subs)
    }
    
  3. 代理工厂: reactive.ts 该模块的核心职责是创建代理对象并维护缓存与身份识别,保证对象不被重复代理。
    // reactive.ts 摘要
    const reactiveMap: WeakMap<object, any> = new WeakMap<object, any>() // target -> proxy 缓存
    const reactiveSet: WeakSet<object> = new WeakSet<object>() // 代理对象身份集合
    
    function createReactiveObject<T extends object>(target: T): T {
      // 1. 防止重复代理:如果是代理对象,直接返回
      if (isReactive(target)) {
        return target
      }
    
      // 2. 缓存检查:如果已代理过,返回旧代理
      const existingProxy = reactiveMap.get(target)
      if (existingProxy) {
        return existingProxy
      }
    
      const proxy = new Proxy(target, mutableHandlers) // 共享 handlers
    
      // 3. 存储缓存和身份
      reactiveMap.set(target, proxy)
      reactiveSet.add(proxy)
    
      return proxy
    }
    
    export function isReactive(target: object) {
      return reactiveSet.has(target) // 身份识别
    }