You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
/** * 创建并返回一个fiberRoot * * @param {Container} container DOM容器 * @param {RootTag} tag fiberRoot节点的标记(LegacyRoot、BatchedRoot、ConcurrentRoot) * @param {(void | RootOptions)} options 配置信息,只有在hydrate时才有值,否则为undefined * @returns */functioncreateRootImpl(container: Container,tag: RootTag,options: void|RootOptions){// Tag is either LegacyRoot or Concurrent Root// 判断是否为hydrate模式consthydrate=options!=null&&options.hydrate===true;consthydrationCallbacks=(options!=null&&options.hydrationOptions)||null;constmutableSources=(options!=null&&options.hydrationOptions!=null&&options.hydrationOptions.mutableSources)||null;// 创建一个fiberRootconstroot=createContainer(container,tag,hydrate,hydrationCallbacks);// 给container附加一个内部属性用于指向fiberRoot的current属性对应的rootFiber节点markContainerAsRoot(root.current,container);constcontainerNodeType=container.nodeType;if(enableEagerRootListeners){constrootContainerElement=container.nodeType===COMMENT_NODE ? container.parentNode : container;listenToAllSupportedEvents(rootContainerElement);}else{if(hydrate&&tag!==LegacyRoot){constdoc=containerNodeType===DOCUMENT_NODE
? container
: container.ownerDocument;// We need to cast this because Flow doesn't work// with the hoisted containerNodeType. If we inline// it, then Flow doesn't complain. We intentionally// hoist it to reduce code-size.eagerlyTrapReplayableEvents(container,((doc: any): Document));}elseif(containerNodeType!==DOCUMENT_FRAGMENT_NODE&&containerNodeType!==DOCUMENT_NODE){ensureListeningTo(container,"onMouseEnter",null);}}if(mutableSources){for(leti=0;i<mutableSources.length;i++){constmutableSource=mutableSources[i];registerMutableSourceForHydration(root,mutableSource);}}returnroot;}
// packages/react-reconciler/src/ReactFiberRoot.new.js > createFiberRoot// Cyclic construction. This cheats the type system right now because// stateNode is any.// 通过createHostRootFiber方法创建fiber tree的根结点,即rootFiber// fiber节点也会像DOM树结构一样形成一个fiber tree单链表树结构// 每个DOM节点或者组件都会生成一个与之对应的fiber节点,在后续的调和(reconciliation)阶段起着至关重要的作用constuninitializedFiber=createHostRootFiber(tag);// 创建完rootFiber之后,会将fiberRoot的实例的current属性指向刚创建的rootFiberroot.current=uninitializedFiber;// 同时rootFiber的stateNode属性会指向fiberRoot实例,形成相互引用uninitializedFiber.stateNode=root;initializeUpdateQueue(uninitializedFiber);// 最后将创建的fiberRoot实例返回returnroot;
FiberRoot
和RootFiber
接下来上面的继续分析
legacyCreateRootFromDOMContainer
方法中的剩余内容,在函数体的结尾返回了调用createLegacyRoot
方法返回的一个ReactSyncRoot
实例。来看createLegacyRoot
方法的定义(packages/react-dom/src/client/ReactDOMRoot.js
):内部又实例化了
ReactDOMBlockingRoot
:内部调用了
createRootImpl
方法,并将返回结果赋值给_internalRoot
,来看createRootImpl
方法的定义:从上述源码中,我们可以看到
createRootImpl
方法通过调用createContainer
方法来创建一个fiberRoot
实例,并将该实例返回并赋值到ReactSyncRoot
构造函数的内部成员_internalRoot
属性上。我们继续深入createContainer
方法去探究一下fiberRoot
完整的创建过程,该方法被抽取到与react-dom
包同级的另一个相关的依赖包react-reconciler
包中,然后定位到packages/react-reconciler/src/ReactFiberReconciler.new.js
:内部调用了
createFiberRoot
方法,定义在packages/react-reconciler/src/ReactFiberRoot.new.js
:一个完整的
FiberRootNode
实例包含了很多有用的属性,这些属性在任务调度阶段都发挥着各自的作用,可以看到完整的FiberRootNode
构造函数的实现(这里只列举部分属性):在了解完了
fiberRoot
的属性结构之后,接下来继续探究createFiberRoot
方法的后半部分内容:看下
createHostRootFiber
,定义在packages/react-reconciler/src/ReactFiber.new.js
:内部调用了
createFiber
,定义在packages/react-reconciler/src/ReactFiber.new.js
:至此我们就成功地创建了一个
fiber
节点,上文中我们提到过,和DOM
树结构类似,fiber
节点也会形成一个与DOM
树结构对应的fiber tree
,并且是基于单链表的树结构,我们在上面刚创建的fiber
节点可作为整个fiber tree
的根节点,即RootFiber
节点。在目前阶段,我们暂时不用关心一个
fiber
节点所包含的所有属性,但可以稍微留意一下以下相关属性:在本小节中我们主要是为了理解
FiberRoot
和RootFiber
这两个容易混淆的概念以及两者之间的联系。同时在这里我们需要特别注意的是,多个fiber
节点可形成基于单链表的树形结构,通过自身的return
,child
和sibling
属性可以在多个fiber
节点之间建立联系。The text was updated successfully, but these errors were encountered: