Skip to content

flushPassiveEffects

Commit 阶段的第一步,其主要作用是:

  1. 对需要被删除的旧节点的 和 存在 Passive 副作用的节点执行 destroy 函数
  2. 对存在 Passive 副作用的节点 执行 create 函数, 并将返回值添加到 update.destroy 中
  3. 对 需要被删除的旧节点按照深度遍历优先的顺序 进行新旧节点的解耦操作

commitPassiveUnmountEffects

  1. 对于移除的旧节点树
  • 通过遍历 fiber.deletions 去 按照父 => 子 的顺序执行 useEffect(HookPassive) 类型的销毁操作
  • 按照按照深度优先的规则 对新旧节点进行解耦操作
js
if ((nextEffect.flags & ChildDeletion) !== NoFlags) {
  // 获取被删除的旧节点数组
  const deletions = fiber.deletions;
  if (deletions !== null) {
    for (let i = 0; i < deletions.length; i++) {
      const fiberToDelete = deletions[i];
      // 将下一个待处理的副作用指向 被移除的旧节点
      nextEffect = fiberToDelete;

      commitPassiveUnmountEffectsInsideOfDeletedTree_begin(
        fiberToDelete,
        fiber
      );
    }

    nextEffect = fiber;
  }
}

其核心是处理 保存在 fiber.deletions 中的需要被移除的旧节点,对于这些旧节点树,其处理流程如下:

js
/**
 * Commit阶段: 执行标记删除的旧节点的
 *  1. 按照 父 => 子 的顺序 执行 effect中HookPassive类型的 destroy 操作
 *  2. 按照深度优先的规则 对新旧节点进行解耦操作
 * @param {*} deletedSubtreeRoot
 * @param {*} nearestMountedAncestor
 */
function commitPassiveUnmountEffectsInsideOfDeletedTree_begin(
  deletedSubtreeRoot: Fiber,
  nearestMountedAncestor: Fiber | null
) {
  while (nextEffect !== null) {
    const fiber = nextEffect;
    // 删除操作的顺序是 父节点 -> 子节点
    setCurrentDebugFiberInDEV(fiber);
    // 执行 HookPassive 类型的副作用的卸载操作
    commitPassiveUnmountInsideDeletedTreeOnFiber(fiber, nearestMountedAncestor);
    resetCurrentDebugFiberInDEV();

    // 如果存在子节点 就优先进入子节点
    const child = fiber.child;
    if (child !== null) {
      child.return = fiber;
      nextEffect = child;
    } else {
      commitPassiveUnmountEffectsInsideOfDeletedTree_complete(
        deletedSubtreeRoot
      );
    }
  }
}
  1. 对于当前 FiberNode 数中的节点

按照深度优先 子 => 兄弟 => 父 的顺序 执行 useEffect(HookPassive) 类型的销毁操作

js
// 2. 对于当前FiberNode数中的节点
// 按照深度优先 子 => 兄弟 => 父 的顺序 执行HookPassive类型的销毁操作
if ((fiber.subtreeFlags & PassiveMask) !== NoFlags && child !== null) {
  child.return = fiber;
  nextEffect = child;
} else {
  commitPassiveUnmountEffects_complete();
}

其是按照深度优先的顺序,找到存在 PassiveMask 副作用的叶子节点,然后对于叶子节点执行 HookPassive 类型的 destroy 操作

commitPassiveMountEffects

按照深度优先的顺序, 执行存在 PassiveMask 副作用的节点 的 create 函数,并将返回值添加到 update.destroy 中

js
/**
 * 按照深度优先的规则执行存在 Passive类型副作用的函数的 effect.create 方法 并将返回值赋值给 effect.destroy
 * @param {*} flags
 * @param {*} finishedWork
 */
function commitHookEffectListMount(flags: HookFlags, finishedWork: Fiber) {
  const updateQueue: FunctionComponentUpdateQueue | null =
    (finishedWork.updateQueue: any);
  const lastEffect = updateQueue !== null ? updateQueue.lastEffect : null;
  if (lastEffect !== null) {
    const firstEffect = lastEffect.next;
    let effect = firstEffect;
    do {
      if ((effect.tag & flags) === flags) {
        // Mount
        // 执行 effect 的 create 方法
        const create = effect.create;
        // 并将create方法的返回值赋值给effect的destroy属性
        effect.destroy = create();
      }
      effect = effect.next;
    } while (effect !== firstEffect);
  }
}