返回

React源码解析之HostComponent的更新(上)

前端

React源码解析之HostComponent的更新(上)

接上篇 React源码解析之completeWork和HostText的更新,本文讲解下HostComponent多次渲染阶段的更新(下篇讲第一次渲染阶段的更新)。

「第一次渲染阶段」放在下篇文章讲。

HostComponent的更新主要是执行了diffProperties()方法,可能你会有疑惑:为什么不直接使用新的props替换旧的props呢?

这是因为有些props不能被直接更改,需要通过更新队列调度更新,而且有些props是不需要直接更新的,只需要重新计算即可。

//省略代码
diffProperties(domElement, type, oldProps, newProps, rootContainerInstance)

diffProperties()方法为React Fiber的更新方法,是React Fiber架构的核心之一,用于比较两个Fiber节点的props,并决定是否需要更新Fiber节点。

React Fiber中的diff算法一文中,我们已经介绍了Fiber的更新算法,这里不再赘述。

//省略代码
const updatePayload = diffProperties(domElement, type, oldProps, newProps, rootContainerInstance);

diffProperties()方法返回一个更新负载对象(updatePayload),该对象包含需要更新的props信息。

//省略代码
updateFiberRefs(domElement, oldProps, newProps);

更新子组件的引用。

//省略代码
for (let i = 0; i < newProps.childCount; i++) {
  //省略代码
  const oldChildFiber = oldProps.childFibers[i];
  //省略代码
  reconcileChildFibers(
    workInProgress,
    current,
    oldFiber.mode,
    type,
    null,
    workInProgress.pendingProps.children,
    currentPrioritizedPlacement,
    newProps.childCount
  );
}

调度子组件的更新。

//省略代码
if (root && workInProgress.child === root) {
  //省略代码
  const newProps = workInProgress.memoizedProps;
  const currentProps = root.memoizedProps;
  const requestUpdate = newProps !== currentProps;
  if (requestUpdate) {
    //省略代码
    enqueueUpdate(root, newProps, null);
  }
}

如果当前Fiber节点是根节点,则将新的props放入更新队列,以便稍后更新根节点。

//省略代码
if (workInProgress.updateQueue !== null) {
  //省略代码
  flushPassiveEffects();
  workInProgress.updateQueue = null;
  //省略代码
}

如果当前Fiber节点有更新队列,则执行更新队列中的所有更新操作。

至此,HostComponent的多次渲染阶段的更新就完成了。

在下篇文章中,我们将讲解HostComponent的第一次渲染阶段的更新。