ReactDOM.render 函數(shù)調(diào)用說明
說明 這里只討論web端初次調(diào)用關于hydrate的全部默認為false|undefinde管跺,不做解釋
ReactDOM.render(element,container,callback)
- element reactElemtn
- container HtmlElemnt
- callback 掛載完成后的回調(diào)
作用: 渲染掛載的開始
檢查 container 是否合法
調(diào)用 legacyRenderSubtreeIntoContainer(null,elemrnt,container,false,callback)
legacyRenderSubtreeIntoContainer
- parentComponent => null --------------- SSR 專用话肖,父結點
- children => element ------------ 需要渲染的 ReactElemtn
- container => container ---------- HtmlElment
- forceHydrate => false -------------- SSR 專用逃片,通過 Hydrate 這里會是 true
- callBack => callback ----------- 同上
作用:根據(jù) container 是否存在 root 區(qū)分初始化/更新槽地,創(chuàng)建或獲取 fiberRoot层释,進而啟動更新
從 container 取出 _reactRootContainer 作為 react 的一個根
const root = container._reactRootContainer
檢查 root 是否存在诊县,如果存在就是 Update座舍,如果不存在就是初始化
若 root 存在:
從 root 中取出 fiberRoot
const fiberRoot = root._internalRoot
調(diào)用 updateContainer(children,fiberRoot,parentComponent,callBack)
注意:這里 callBack 會通過 getPublicRootInstance() 遞歸找到 fiberRoot 上第一個非 HTMlElement 結點,并將 callback 綁定在它上邊港令。
if (typeof callback === 'function') {
const originalCallback = callback;
callback = function() {
const instance = getPublicRootInstance(fiberRoot);
originalCallback.call(instance);
};
}
若 root 不存在:
調(diào)用 legacyCreateRootFromDOMContainer(contaiber,forceHydrate) 初始化 root淡喜。
將 root 賦值給 container._reactRootContainer,取出 root 中的_internalRoot 作為 fiberRoot秕磷。
調(diào)用 updateContainer(children,fiberRoot,parentComponent,callBack)。
//注意這里調(diào)用的時候拆火,是非批量的跳夭。因為是初始化的內(nèi)部掛載,所以需要使用非批量更新
unbatchedUpdates(() => {
updateContainer(children, fiberRoot, parentComponent, callback);
});
// updateContainer() 就到了更新流程了们镜,這里不討論了^-^
legacyCreateRootFromDOMContainer
- container --------------- HTMLElement
- forceHydrate ------------ 同上
作用:清空 container,創(chuàng)建 root
- 根據(jù) forceHydrate 和 container 上是否已經(jīng)被標記是一個 ReactContainer 來判斷是否需要清空 container(SSR 不需要清空币叹,但是 web 端初始化情況)
- 創(chuàng)建一個 root 結點
shouleHydrate = forceHydrate && isReactContainer(contaiber)?{ hydrate:true }:undefinde
調(diào)用 createLegacyRoot(container,shouleHydrate)
createLegacyRoot
- container --------------- HTMLElement
- options:shouleHydrate --- 忽略
引入靜態(tài)變量 LegacyRoot = 0 ,作為 RootTag
調(diào)用 new ReactDOMBlockingRoot(container,LegacyRoot,options)
ReactDOMBlockingRoot
- container --------------- HTMLElement
- tag --------------------- root 的 tag 表示構建 root 的來源
- options ----------------- 忽略
創(chuàng)建 RootImpl 模狭,賦值給 this._internalRoot 也就是 fiberRoot
this._internalRoot = createRootImpl(container, tag, options);
//注意:通過 ReactDOMBlockingRoot 創(chuàng)建的實例會自動實現(xiàn)兩個函數(shù) render 和 unmount
// 渲染根結點
render(children){
root = this.\_internalRoot;
updateContainer(children,root,null,null)
}
// 卸載根結點
unmount(){
const root = this._internalRoot;
const container = root.containerInfo;
updateContainer(null, root, null, () => {
// 從container中移除 __reactContainer 對應的fiber
unmarkContainerAsRoot(container);
});
}
createRootImpl
- container --------------- HTMLElement
- tag --------------------- root 的 tag 表示構建 root 的來源
- options ----------------- 忽略
作用:
- 根據(jù) container 創(chuàng)建 root
- 標記 container 作為 root 的 current
- 為 root 容器添加所有監(jiān)聽事件
根據(jù) container 創(chuàng)建 root
const root = createContainer(container, tag, hydrate, hydrationCallbacks);
標記 container 作為 root 的 current
// 為 container 字段 添加 __reactContainer 對應的 fiber
markContainerAsRoot(root.current, container);
為 root 容器添加所有監(jiān)聽事件
const rootContainerElement = container.nodeType === COMMENT_NODE ? container.parentNode : container;
// 綁定事件監(jiān)聽颈抚,特殊處理selectionchange
listenToAllSupportedEvents(rootContainerElement);
createContainer -> createFiberRoot
- containerInfo --------------- HTMLElement
- tag ------------------------- root 的 tag 表示構建 root 的來源
作用:
-
創(chuàng)建 root:FiberRoot
root = new FiberRootNode(containerInfo,tag)
-> root.containerInfo = containerInfo
-> root.tag = tag
-
創(chuàng)建 RootFiber:Fiber
RootFiber = createHostRootFiber(tag);
根據(jù) tag 生成一個 mode,web 初始化出來的 mode === NodeMode
HostRoot = 3; // 表示創(chuàng)建的是 根結點
調(diào)用 createFiber(HostRoot,null,null,mode)
-> RootFiber.tag = HostRoot
-> RootFiber.mode = mode
-
形成一個閉環(huán)贩汉,將 root.current 指向 RootFiber锚赤,并將 root 作為 Fiber 的第一個 stateNode
root.current = RootFiber
RootFiber.stateNode = root
-
初始化 RootFiber 的 UpdateQueue
initializeUpdateQueue(RootFiber)
->queue.baseState = RootFiber.memoizedState
->RootFiber.updateQueus = queue
createFiber
- tag ------------------------- fiber 的類型
- penddingProps --------------- 外界數(shù)據(jù)
- key ------------------------- 唯一表識
- mode ------------------------ 基本都是 NodeMode
作用:
生成一個 FiberNode
FiberNode.tag = tag
FiberNode.penddingProps = penddingProps
FiberNode.mode=mode
FiberNode.key = key