Skip to content

依赖收集

  • 依赖收集发生在数据的访问阶段 当数据被访问 会执行 get 函数
  • get 函数 是执行 createGetter 函数的返回值 isReadonly 默认 false

get

  • get 函数主要做了 4件事
  • 对特殊的 key 做了 代理 比如: __v_raw 返回原始对象 target
  • 如果 target 是数组 并且命中了 arrayInstrumentations 执行内部对应函数
  • 通过 Reflect.get 函数求值 并执行 track 函数收集依赖
  • 对象属性访问的时候才会判断子属性的类型 决定是否要递归执行 reactive

arrayInstrumentations

  • 重写了数组中的 includes indexOf lastIndexOf 函数
  • 当对响应式对象调用 这三个函数 就会 对数组的每一个 元素都进行代理 做依赖收集

track

  • 创建了全局的 targetMap作为原始数据对象的 Map
  • 键是 target 值是 depsMap 用来作为依赖的 Map
  • depsMap 键是 target 的key 值是 dep 集合
  • dep 集合 中存储的是依赖的副作用函数
  • 每次执行 track 函数 就会把当前激活副作用函数 activeEffect 作为依赖
  • 收集到 与target 相关的 depsMap 对应 key 下的依赖集合 dep 中
ts

const arrayInstrumentations = /*#__PURE__*/ createArrayInstrumentations()

function createArrayInstrumentations() {
  const instrumentations: Record<string, Function> = {}
  // instrument identity-sensitive Array methods to account for possible reactive
  // values
  ;(['includes', 'indexOf', 'lastIndexOf'] as const).forEach(key => {
    instrumentations[key] = function (this: unknown[], ...args: unknown[]) {
      const arr = toRaw(this) as any
      for (let i = 0, l = this.length; i < l; i++) {
        track(arr, TrackOpTypes.GET, i + '')
      }
      // we run the method using the original args first (which may be reactive)
      const res = arr[key](...args)
      if (res === -1 || res === false) {
        // if that didn't work, run it again using raw values.
        return arr[key](...args.map(toRaw))
      } else {
        return res
      }
    }
  })
  // instrument length-altering mutation methods to avoid length being tracked
  // which leads to infinite loops in some cases (#2137)
  ;(['push', 'pop', 'shift', 'unshift', 'splice'] as const).forEach(key => {
    instrumentations[key] = function (this: unknown[], ...args: unknown[]) {
      pauseTracking()
      const res = (toRaw(this) as any)[key].apply(this, args)
      resetTracking()
      return res
    }
  })
  return instrumentations
}

Welcome to the site