返回
React源码解析之HostComponent的更新(上)
前端
2023-09-22 17:05:12
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的第一次渲染阶段的更新。