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
ReactElememt 函数创建的 element 都是 symbol(react.element)
props
接收的 props 和 children
FiberRoot
functionFiberRootNode(containerInfo,tag,hydrate){this.tag=tag;this.current=null;// fiber tree 的根节点this.containerInfo=containerInfo;// root domthis.hydrate=hydrate;// 是否要与以后的 dom 融合this.pendingChildren=null;this.pingCache=null;this.finishedExpirationTime=NoWork;this.finishedWork=null;this.timeoutHandle=noTimeout;this.context=null;this.pendingContext=null;this.callbackNode=null;this.callbackPriority=NoPriority;this.firstPendingTime=NoWork;this.firstSuspendedTime=NoWork;this.lastSuspendedTime=NoWork;this.nextKnownPendingLevel=NoWork;this.lastPingedTime=NoWork;this.lastExpiredTime=NoWork;this.interactionThreadID=tracing.unstable_getThreadID();this.memoizedInteractions=newSet();this.pendingInteractionMap=newMap();}
exportconstFunctionComponent=0;exportconstClassComponent=1;exportconstIndeterminateComponent=2;// Before we know whether it is function or class,未知类型exportconstHostRoot=3;// Root of a host tree. Could be nested inside another node.exportconstHostPortal=4;// A subtree. Could be an entry point to a different renderer.exportconstHostComponent=5;// html tagexportconstHostText=6;// textexportconstFragment=7;exportconstMode=8;exportconstContextConsumer=9;exportconstContextProvider=10;exportconstForwardRef=11;exportconstProfiler=12;exportconstSuspenseComponent=13;exportconstMemoComponent=14;exportconstSimpleMemoComponent=15;exportconstLazyComponent=16;exportconstIncompleteClassComponent=17;
effectTags
副作用类型,标记每个更新的类型,作相应的处理
exportconstNoEffect=/* */0b00000000000;exportconstPerformedWork=/* */0b00000000001;// You can change the rest (and add more).exportconstPlacement=/* */0b00000000010;// 插入/移到exportconstUpdate=/* */0b00000000100;// props 更新exportconstPlacementAndUpdate=/* */0b00000000110;exportconstDeletion=/* */0b00000001000;exportconstContentReset=/* */0b00000010000;exportconstCallback=/* */0b00000100000;exportconstDidCapture=/* */0b00001000000;exportconstRef=/* */0b00010000000;exportconstSnapshot=/* */0b00100000000;// Update & Callback & Ref & SnapshotexportconstLifecycleEffectMask=/* */0b00110100100;// Union of all host effectsexportconstHostEffectMask=/* */0b00111111111;exportconstIncomplete=/* */0b01000000000;exportconstShouldCapture=/* */0b10000000000;
// 渲染阶段scheduleUpdateOnFiberperformSyncWorkOnRootworkLoopSyncperformUnitOfWorkbeginWork// 通过父 fiber 生成 child element 相应的 fiber,循环完,最终会生成整颗 fiber tree/updateFunctionComponent// 函数组件执行,hook dispatcher 绑定/updateClassComponent// 类组件执行,相关生命函数执行/updateHostRoot/updateHostComponent/updateHostTextreconcileChildren// child element to fibercompleteUnitOfWorkcompleteWork// 给每个 fiber 创建 dom 实例,同时存到对应 fiber.stateNode。循环将子的 dom 实例插入到父的 dom 实例中。然后初始化每个 fiber.statenode 的 dom 属性、事件等finishSyncRender// 如果是组件,执行相关的生命函数、hook。将 hostfiber.stateNode 插入到 dom root。最后执行 callback
reactElement
FiberRoot
FiberNode
tag
effectTags
update & updateQueue
渲染阶段
render(element, container, callback)
return legacyRenderSubtreeIntoContainer(null, element, container, false, callback)
root = container._reactRootContainer = legacyCreateRootFromDOMContainer(container, forceHydrate)
封装 render 传入的 callback
updateContainer(children, fiberRoot, parentComponent, callback)
scheduleWork(current$1, expirationTime) ,即执行 scheduleUpdateOnFiber 函数
performSyncWorkOnRoot(root),同步的任务处理,还有 performConcurrentWorkOnRoot 模式的
workLoopSync(),执行该函数直到完成,执行不同组件的初始化,生成 fiber node
函数组件执行
,这里可能多次执行组件实例化
getDerivedStateFromProps
componentWillMount
事件绑定
,ensureListeningTo(rootContainerElement, propKey)finishSyncRender,对 fiber node 生成 dom 片段,插入 dom
commitRoot,commitRootImpl,
commitBeforeMutationEffects
commitMutationEffects
commitLayoutEffects,执行生命周期函数
commitLifeCycles
flushSyncCallbackQueue,执行 render 传入的 callback
总结
更新阶段
setstate
var fiber = get(inst),根据 instance 找到对应的 fiber node
enqueueSetState,创建一个 update,将 update 存到链表中的 sharedQueue.pending
scheduleWork,即 scheduleUpdateOnFiber,进入循环更新
只有一个节点时,update 对象的 next 执行自身。循环链表
payload,setstate 传入的对象
当连续 setstate 时
正常情况:
事件循环情况:
当 setState 被推到事件循环中时,由于事件循环的机制,所有的任务都是分开执行的,所以每个 setstate 会执行一次调度更新
forceupdate
replaceState
useState
总结
触发更新动作,创建 update 存到对应的 fiber.updateQueue.shared.pending.payload 上,当多个更新触发时,会通过 next 指针形成链表。
每个 update 都是由更新动作触发而创建的。forceupdate/replacestate/setstate/usestate 的调用都会转化为一个个 update 对象,最后形成 update 链表
多个 setState 触发会如何?
事件系统
事件是如何绑定的?
p 标签上有 onclick 事件,p 标签的父是 div
在 div 对应的 fiber 调和子节点的时候生成 p 的 fiber,p 的事件还存在 p fiber.pendingProps 上。beginwork 完成后会将 fiber.pendingProps 上的属性存到 fiber.memoizedProps 上。即事件回调存到了 fiber.memoizedProps 上
在 completeWork 时,创建 fiber.stateNode。然后在 updateFiberProps 函数中 fiber.memoizedProps 赋给 fiber.stateNode
渲染阶段,在 finalizeInitialChildren 函数里进行
setInitialProperties,对某些标签的事件进行绑定,如:load,error,reset,submit,toggle,invalid 等,对表单元素会做很多额外的封装
setInitialDOMProperties,设置 dom style,innerhtml,innertext,通过 ensureListeningTo 进行事件绑定等。这里的事件绑定是代理到 dom root/document 的
ensureListeningTo,除了绑定对应的事件,还有其他相同组的事件,
如:绑定的是 onchange,但 react 同时还会绑定 ["blur", "change", "click", "focus", "input", "keydown", "keyup", "selectionchange"]
react 会将事件回调进行封装。比如,onchange = () => {console.log('hi')}。这个事件回调是存在 fiber.stateNode 上的
在事件绑定的时候,通过 dispatchDiscreteEvent 返回事件回调。即事件回调是被 dispatchDiscreteEvent 封装了
discreteUpdates
事件是如何执行的?
hook
hook 是如何执行的?
useState
mountState(initialState)
创建一个空的 hook 对象,计算 initialstate,因为有可能是函数,将 state 存到 hook.baseState 上,同时初始化 hook.queue, 绑定 hook.dispatcher
dispatchAction
useRef
mountRef(initialValue)
创建一个空的 hook 对象,创建 ref 对象,将 ref 对象存到 hook 上
useEffect
mountEffect(create, deps)
mountEffectImpl(Update | Passive, Passive$1, create, deps)
创建一个 hook,标记 effectTag = fiberEffectTag,将 effect 挂到 hook.memoizedState 上
useCallback
useContext
readContext(callback, deps)
useLayoutEffect
mountLayoutEffect(create, deps)
mountEffectImpl
useReducer
当组件多长执行时,只是重复创建 hook ,相当于 hook 的初始化,不会进行 hook 的执行。hook 还没有和 fiber 相关联
但 seta 的时候,会进行 dispatch 当前的 fiber 和当前的 hook.queue
context
ref
concurrent mode
整体的 fiber tree
递归流程
渲染流程
流程回顾
hastFiber,对 updateQueue.shared.pending.payload 上的 react element(即 app 组件) 生成对应的 fiber
然后通过 app fiber 去 reconcileChildren 调合 children element 的到 children fiber。最终完成整颗 fiber tree
在 completeWork 的时候将 instance 存到 fiber.stateNode
fiber tree 创建后,会进行 finishSyncRender 生成每个 fiber 对应的 stateNode
整体流程分为:
概览图
The text was updated successfully, but these errors were encountered: