React 16 源码瞎几把解读 【三 点 二】 react中的fiberRoot
〇、先来看看常用的常量
NoWork = 0
noTimeout = undefined
HostRoot = 3
NoContext = 0b000;
AsyncMode = 0b001;
StrictMode = 0b010;
ProfileMode = 0b100;
NoEffect = /* */ 0b00000000000
enableProfilerTimer = __PROFILE__
__PROFILE__: true
isDevToolsPresent = typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ !== 'undefined'
一、制造root._internalRoot 的 createFiberRoot 方法
1 export function createFiberRoot( 2 containerInfo: any, // id=app 的 dom 3 isAsync: boolean, // false 4 hydrate: boolean, // false 5 ): FiberRoot { 6 const uninitializedFiber = createHostRootFiber(isAsync); 7 const root = { 8 current: uninitializedFiber, // 添加fiber 属性 一直用它 9 containerInfo: containerInfo, // dom app 10 pendingChildren: null, 11 12 earliestPendingTime: NoWork, 13 latestPendingTime: NoWork, 14 earliestSuspendedTime: NoWork, 15 latestSuspendedTime: NoWork, 16 latestPingedTime: NoWork, 17 18 didError: false, 19 20 pendingCommitExpirationTime: NoWork, 21 finishedWork: null, 22 timeoutHandle: noTimeout, 23 context: null, 24 pendingContext: null, 25 hydrate, //false 26 nextExpirationTimeToWorkOn: NoWork, 27 expirationTime: NoWork, 28 firstBatch: null, 29 nextScheduledRoot: null, 30 }; 31 uninitializedFiber.stateNode = root; 32 return root; 33 }
通过上面的代码得知,造出来的root._internalRoot 是一个包含若干属性的对象,其中最重要的是一个名叫 current的属性,这个current属性在上一集我们说到虚拟dom渲染过程的时候被当做第一参数 传入了 渲染核心函数 enqueueUpdate中。
这个current属性是个核心
二、 制造current属性的createHostRootFiber(isAsync)方法
1 export function createHostRootFiber( 2 isAsync: boolean // false 3 ): Fiber { 4 // export type TypeOfMode = number; 5 // export const NoContext = 0b000; 6 // export const AsyncMode = 0b001; 7 // export const StrictMode = 0b010; 8 // export const ProfileMode = 0b100; 9 let mode = isAsync ? AsyncMode | StrictMode : NoContext; // 0b000 10 // __PROFILE__: true, 11 // export const enableProfilerTimer = __PROFILE__; 12 // export const isDevToolsPresent = typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ !== 'undefined'; 13 if (enableProfilerTimer && isDevToolsPresent) { 14 // Always collect profile timings when DevTools are present. 15 // This enables DevTools to start capturing timing at any point– 16 // Without some nodes in the tree having empty base times. 17 mode |= ProfileMode; // 0b100 18 } 19 // export const HostRoot = 3; // Root of a host tree. Could be nested inside another node. 20 return createFiber(HostRoot, null, null, mode); 21 }
这些代码无非是通过入参 isAsync 确定了mode的值,用来决定创造出的current是个具有根节点属性的东西
三、通用方法createFiber -> new FiberNode(...)
createFiber方法只是简单的返回了 new FiberNode(...),我们只需要看FiberNode是个啥
1 function FiberNode( 2 tag: TypeOfWork, 3 pendingProps: mixed, 4 key: null | string, 5 mode: TypeOfMode, 6 ) { 7 // Instance 8 this.tag = tag; 9 this.key = key; 10 this.type = null; 11 this.stateNode = null; 12 13 // Fiber 14 this.return = null; 15 this.child = null; 16 this.sibling = null; 17 this.index = 0; 18 19 this.ref = null; 20 21 this.pendingProps = pendingProps; 22 this.memoizedProps = null; 23 this.updateQueue = null; 24 this.memoizedState = null; 25 this.firstContextDependency = null; 26 27 this.mode = mode; 28 29 // Effects 30 // export const NoEffect = /* */ 0b00000000000; 31 this.effectTag = NoEffect; 32 this.nextEffect = null; 33 34 this.firstEffect = null; 35 this.lastEffect = null; 36 37 this.expirationTime = NoWork; // 0 38 this.childExpirationTime = NoWork; // 0 39 40 this.alternate = null; 41 42 if (enableProfilerTimer) { 43 this.actualDuration = 0; 44 this.actualStartTime = 0; 45 this.selfBaseDuration = 0; 46 this.treeBaseDuration = 0; 47 } 48 }
附加了一堆将来fiber架构需要用到的属性,具体这些属性是干啥用的,咱们以后再分析
不知道大家还记不记得这个root从我们调用reactDOM.render 传入那个container 往上附加了多少有用的东西,现在来回顾一下:
container 就是咱们传入的那个真实dom
container = { _reactRootContainer :{ // legacyCreateRootFromDOMContainer _internalRoot: { // DOMRenderer.createContainer current:{} // new FiberNode } } }
在dom上附加了这么一串有用的对象