ReactDom.render
//packages/react-dom/src/client/ReactDOMLegacy.js
render(
element: React$Element,
container: DOMContainer,
callback: ?Function,
) {
// 调用legacyRenderSubtreeIntoContainer
return legacyRenderSubtreeIntoContainer(
null,
element,
container,
false,
callback,
);
}
function legacyRenderSubtreeIntoContainer(
parentComponent: ?React$Component,
children: ReactNodeList,
container: DOMContainer,
forceHydrate: boolean,
callback: ?Function,
){
let root = container._reactRootContainer
let fiberRoot
// 判断root是否存在
if(!root) {
// 首次渲染不存在,则生成root,赋值fiberRoot
root = container_reactRootContainer = legacyCreateRootFromDOMContainer(container,forceHydrate)
fiberRoot = root._internalRoot
/**fiberRoot :{tag: 0
current: FiberNode {tag: 3, key: null, elementType: null, type: null, stateNode: FiberRootNode, …}
containerInfo: div#root
finishedExpirationTime: 0
finishedWork: null} **/
// 字面理解不要批量更新,首次渲染需要立即执行内部函数,即updateContainer
unbatchedUpdates(() => {
// 生成expirationTime, 调度 ps: 注释1
updateContainer(children, fiberRoot, parentComponent, callback);
});
}else {
fiberRoot = root._internalRoot
updateContainer(children, fiberRoot, parentComponent, callback);
}
return getPublicRootInstance(fiberRoot)
}
// 注释1 生成expirationTime, 并 scheduleWork调度
function updateContainer(
element: ReactNodeList,
container: fiberRoot,
parentComponent: ?React$Component,
callback: ?Function,
): ExpirationTime {
const current = container.current; // 当前Root Fiber
const currentTime = requestCurrentTimeForUpdate(); //当前时间
// 生成expirationTime 注释2
const expirationTime = computeExpirationForFiber(
currentTime,
current,
suspenseConfig,
);
// 创建更新
const update = createUpdate(expirationTime, suspenseConfig)
enqueueUpdate(current, update); // 加入队列
// 注释 3
scheduleWork(current, expirationTime) //调度root fiber
return expirationTime
}
// 注释2 计算expirationTime
function computeExpirationForFiber(
currentTime,
fiber,
suspenseConfig
): ExpirationTime {
const priorityLevel = getCurrentPriorityLevel();
let expirationTime;
if(suspenseConfig !== null) {
//有挂起任务的情况
}else{
switch(priorityLevel) {
case ImmediatePriority:
expirationTime = Sync // 同步
break;
case NormalPriority:
case LowPriority:
expirationTime = computeAsyncExpiration(currentTime) //异步
}
}
return expirationTime;
}
// 注释 3 scheduleWork调度
function scheduleUpdateOnFiber(
fiber,
expirationTime
) {
if(expirationTime === Sync) {
//注释4
performSyncWorkOnRoot(root)
}else {
}
}
// 注释 4
function performSyncWorkOnRoot(root) {
if(workInProgress !== null) {
do{
try {
// 注释 5
workLoopSync()
}
}while(true)
}
if(workInProgress !==null){
}else{
// 已经没有当前工作的单元任务,提交 注释7
commitRoot(root)
}
}
// 注释 5
function workLoopSync() {
// 向下遍历,构建fiber tree
while (workInProgress !== null) {
// 注释 6
workInProgress = performUnitOfWork(workInProgress);
}
}
// 注释 6 构建fiber tree, 并返回下一个fiber node
function performUnitOfWork(unitOfWork) {
const current = unitOfWork.alternate
startWorkTimer(unitOfWork)
let next
// 向下构建fiber tree,更加tag 进行updatexx,如果nextProps中有children ,惊喜reconcileChildren
next = beginWork(current, unitOfWork, renderExpirationTime)
if(next === null){
// 向上构建,设置firstEffect/nextEffect,并设置stateNode,真实dom
next = completeUnitOfWork(unitOfWork)
}
return next
}
// 注释7 commitRoot(root)
function commitRootImpl(root, renderPriorityLevel){
const finishedWork = root.finishedWork
/** finishedWork:
{ tag: 3
key: null
elementType: null
type: null
stateNode: FiberRootNode {tag: 0, current: FiberNode, containerInfo: div#root, pendingChildren: null, pingCache: null, …}
return: null
child: FiberNode {tag: 1, key: null, stateNode: Demo, elementType: ƒ, type: ƒ, …}
sibling: null
index: 0
ref: null
pendingProps: null
memoizedProps: null
updateQueue: {baseState: {…}, firstUpdate: null, lastUpdate: null, firstCapturedUpdate: null, lastCapturedUpdate: null, …}
memoizedState: {element: {…}}
mode: 8
effectTag: 0
nextEffect: null
firstEffect: FiberNode {tag: 1, key: null, stateNode: Demo, elementType: ƒ, type: ƒ, …}
lastEffect: FiberNode {tag: 1, key: null, stateNode: Demo, elementType: ƒ, type: ƒ, …}
expirationTime: 0
childExpirationTime: 0
alternate: FiberNode {tag: 3, key: null, elementType: null, type: null, stateNode: FiberRootNode, …}
}
**/
firstEffect = finishedWork.firstEffect;
nextEffect = firstEffect
// 根据fiberRoot上 nextEffect,进行更新
do{
commitBeforMutationEffects()
}while(nextEffect !== null)
do{
// 根据nextEffect.effectTag 做响应的dom操作 commitPlacement/commitWork/commitDeletion
commitMutationEffects()
}while(nextEffect !== null)
do{
// commitLifeCycles 执行后续的生命周期
commitLayoutEffects(root, expirationTime)
}while(nextEffect !== null)
onCommitRoot(finishedWork.stateNode, expirationTime)
flushSyncCallbackQueue()
return null;
}