【React源码学习】2 mount阶段compleleWork工作流程


测试代码如下

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阶段函数调用关系如下
completeWork
mount阶段的completeWork大概做了两件事

  • 根据Fiber创建真实DOM
  • 将真实DOM挂载到stateNode上

Author: Maple
Reprint policy: All articles in this blog are used except for special statements CC BY 4.0 reprint polocy. If reproduced, please indicate source Maple !
  TOC