测试代码如下
class App extends React.Component {
render() {
return (
<div className="container">
<h1>我是标题一</h1>
标题二
</div>
);
}
}
performUnitOfWork
看一下源码
function performUnitOfWork(unitOfWork) {
var current = unitOfWork.alternate;
setCurrentFiber(unitOfWork);
var next;
if ( (unitOfWork.mode & ProfileMode) !== NoMode) {
startProfilerTimer(unitOfWork);
next = beginWork$1(current, unitOfWork, subtreeRenderLanes);
stopProfilerTimerIfRunningAndRecordDelta(unitOfWork, true);
} else {
next = beginWork$1(current, unitOfWork, subtreeRenderLanes);
}
resetCurrentFiber();
unitOfWork.memoizedProps = unitOfWork.pendingProps;
if (next === null) {
completeUnitOfWork(unitOfWork);
} else {
workInProgress = next;
}
ReactCurrentOwner$2.current = null;
}
beginwork和completework都发生在同一个函数中,performUnitOfWork会不断调用beginwork创建workInProgress树,如果返回的next是null,表明当前fiber树达到最大深度(DFS),可以调用completeUnitOfWork(如果该节点只存在一个文本子节点,react会进行优化,不再调用beginwork,因此第一个进入completeUnitOfWork的是h1的fiber)
completeWork
completeWork函数内会根据不同的workInProgress.tag进入不同的代码块,此时workInProgress == 5,进入HostComponent代码块。
此时使用下面的代码判断mount阶段
if (current !== null && workInProgress.stateNode != null) {
updateHostComponent$1(current, workInProgress, type, newProps, rootContainerInstance);
if (current.ref !== workInProgress.ref) {
markRef$1(workInProgress);
}
}
由于current和stateNode都是null,进入else
var instance = createInstance(type, newProps, rootContainerInstance, currentHostContext, workInProgress);
appendAllChildren(instance, workInProgress, false, false);
workInProgress.stateNode = instance;
if (finalizeInitialChildren(instance, type, newProps, rootContainerInstance)) {
markUpdate(workInProgress);
}
该阶段涉及DOM节点的创建
createInstance
看一下源码
function createInstance(type, props, rootContainerInstance, hostContext, internalInstanceHandle) {
var parentNamespace;
{
var hostContextDev = hostContext;
validateDOMNesting(type, null, hostContextDev.ancestorInfo);
if (typeof props.children === 'string' || typeof props.children === 'number') {
var string = '' + props.children;
var ownAncestorInfo = updatedAncestorInfo(hostContextDev.ancestorInfo, type);
validateDOMNesting(null, string, ownAncestorInfo);
}
parentNamespace = hostContextDev.namespace;
}
var domElement = createElement(type, props, rootContainerInstance, parentNamespace);
precacheFiberNode(internalInstanceHandle, domElement);
updateFiberProps(domElement, props);
return domElement;
}
该函数对props进行了处理,嗲用createElement创建了一个真实DOM
appendAllChildren
由于workInProgress的child是null,函数直接return
finalizeInitialChildren
将创建的instance挂载到stateNode后,调用finalizeInitialChildren进行属性的初始化。
summary
completeWork阶段函数调用关系如下
mount阶段的completeWork大概做了两件事
- 根据Fiber创建真实DOM
- 将真实DOM挂载到stateNode上