trigger触发依赖(6)

trigger主要工作过程是把依赖提取出来,然后一个个执行,下面简述其过程。

export function trigger(
  target: object,
  type: TriggerOpTypes,
  key?: unknown,
  newValue?: unknown,
  oldValue?: unknown,
  oldTarget?: Map<unknown, unknown> | Set<unknown>
) {
  // 条件1
  const depsMap = targetMap.get(target)
  if (!depsMap) {
    // never been tracked
    return
  }
  // 条件2
  let deps: (Dep | undefined)[] = []
   // ①
  if (type === TriggerOpTypes.CLEAR) {
    // collection being cleared
    // trigger all effects for target
    deps = [...depsMap.values()]
  // ②
  } else if (key === 'length' && isArray(target)) {
    const newLength = Number(newValue)
    depsMap.forEach((dep, key) => {
      if (key === 'length' || key >= newLength) {
        deps.push(dep)
      }
    })
 // ③
  } else {
    // schedule runs for SET | ADD | DELETE
    if (key !== void 0) {
      deps.push(depsMap.get(key))
    }

    // also run for iteration key on ADD | DELETE | Map.SET
    switch (type) {
      case TriggerOpTypes.ADD:
        if (!isArray(target)) {
          deps.push(depsMap.get(ITERATE_KEY))
          if (isMap(target)) {
            deps.push(depsMap.get(MAP_KEY_ITERATE_KEY))
          }
        } else if (isIntegerKey(key)) {
          // new index added to array -> length changes
          deps.push(depsMap.get('length'))
        }
        break
      case TriggerOpTypes.DELETE:
        if (!isArray(target)) {
          deps.push(depsMap.get(ITERATE_KEY))
          if (isMap(target)) {
            deps.push(depsMap.get(MAP_KEY_ITERATE_KEY))
          }
        }
        break
      case TriggerOpTypes.SET:
        if (isMap(target)) {
          deps.push(depsMap.get(ITERATE_KEY))
        }
        break
    }
  }
   // 条件3
  const eventInfo = __DEV__
    ? { target, type, key, newValue, oldValue, oldTarget }
    : undefined
 // a
  if (deps.length === 1) {
    if (deps[0]) {
      if (__DEV__) {
        triggerEffects(deps[0], eventInfo)
      } else {
        triggerEffects(deps[0])
      }
    }
  // b
  } else {
    const effects: ReactiveEffect[] = []
    for (const dep of deps) {
      if (dep) {
        effects.push(...dep)
      }
    }
    if (__DEV__) {
      triggerEffects(createDep(effects), eventInfo)
    } else {
      triggerEffects(createDep(effects))
    }
  }
}

1.获取依赖映射targetMap中当前(要触发依赖执行的对象target)的映射,如果映射不存在则直接返回

2.设置依赖数组deps,根据依赖触发类型,来收集依赖。
①如果依赖的触发类型type是clear,则把当前对象所有属性方法的依赖全部丢到deps数组中

②如果触发依赖对象是数组,且触发类型是length。deps收集关于length的依赖以及index大于新值的所有依赖

③其他情况。如果非长度为0的属性和方法,直接收集对应方法的依赖。
在触发类型type是add的情况下,如果对象不是数组,则deps收集对象target依赖映射targetMap中关于ITERATE_KEY的依赖,如果对象target是map类型,则deps收集对象target依赖映射targetMap中关于MAP_KEY_ITERATE_KEY的依赖。
在触发类型是delete的情况下,操作跟add的一样。
在触发类型是set的情况下,如果对象target是map类型,则deps收集对象target依赖映射targetMap中关于ITERATE_KEY的依赖。

3.根据依赖数组deps的长度,来分别触发依赖。
a.如果deps的长度为1且有效,通过triggerEffects触发依赖执行
b.其他情况,过滤获取有效依赖,然后由createDep包裹依赖再通过triggerEffects触发依赖执行

triggerEffects函数主要是获取每项依赖,然后调用triggerEffect方法来执行每项依赖,triggerEffects方法体如下

export function triggerEffects(
  dep: Dep | ReactiveEffect[],
  debuggerEventExtraInfo?: DebuggerEventExtraInfo
) {
  // spread into array for stabilization
  const effects = isArray(dep) ? dep : [...dep]
  for (const effect of effects) {
    if (effect.computed) {
      triggerEffect(effect, debuggerEventExtraInfo)
    }
  }
  for (const effect of effects) {
    if (!effect.computed) {
      triggerEffect(effect, debuggerEventExtraInfo)
    }
  }
}

triggerEffect函数简述如下
1.必须满足传入的副作用函数(依赖)不是当前副作用函数,或者副作用函数可被执行才能进行触发依赖
2.满足1条件下,如果副作用存在调度方法,则执行调度方法,否则执行该副作用函数

function triggerEffect(
  effect: ReactiveEffect,
  debuggerEventExtraInfo?: DebuggerEventExtraInfo
) {
  // 条件1
  if (effect !== activeEffect || effect.allowRecurse) {
    if (__DEV__ && effect.onTrigger) {
      effect.onTrigger(extend({ effect }, debuggerEventExtraInfo))
    }
  // 条件2
    if (effect.scheduler) {
      effect.scheduler()
    } else {
      effect.run()
    }
  }
}

现在派发阶段已经知道,那副作用函数effect长哪样呢?我们下文继续!
本人菜鸡,有问题望前辈及时指出,不胜感激!!

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容