React Fiber的創(chuàng)建
當(dāng)前React版本基于V17.0.2版本,本篇主要介紹fiber結(jié)構(gòu)的創(chuàng)建。
一、開始之前
個人理解,如有不對,請指出。
首先需要配置好React的debugger開發(fā)環(huán)境,入口在這里:github
執(zhí)行npm run i,安裝依賴,npm start運行環(huán)境。
二、從React.render開始
通過在項目入口處調(diào)用React.render,打上Debug,查看React調(diào)用棧。
const root = document.getElementById("root"); ReactDOM.render( <React.StrictMode> <App /> </React.StrictMode>, root );
在React調(diào)用render之后,在傳入基礎(chǔ)的配置后,調(diào)用legacyRenderSubtreeIntoContainer。
export function render( element: React$Element<any>, container: Container, callback: ?Function, ) { // 刪除一些環(huán)境代碼 // ... return legacyRenderSubtreeIntoContainer( null, element, container, false, callback, ); }
在React調(diào)用render之后,在傳入基礎(chǔ)的配置后,調(diào)用legacyRenderSubtreeIntoContainer。
export function render( element: React$Element<any>, container: Container, callback: ?Function, ) { // 刪除一些環(huán)境代碼 // ... return legacyRenderSubtreeIntoContainer( null, element, container, false, callback, ); }
legacyRenderSubtreeIntoContainer一共做了兩件事情,一個是生成了fiberRoot,一個是調(diào)用updateContainer。
進入legacyCreateRootFromDOMContainer函數(shù),查看如何生成fiberRoot。 在函數(shù)內(nèi)部,調(diào)用了createLegacyRoot,在這里區(qū)分了下,是否使用hydrate,如下:
return createLegacyRoot( container, shouldHydrate ? { hydrate: true, } : undefined, );
對于createLegacyRoot來說,是用來實例化ReactDOMLegacyRoot函數(shù)的,通過后續(xù)調(diào)用,終于進入到root的生成,調(diào)用createRootImpl函數(shù),實例化root。
進入createFiberRoot函數(shù),初始化FiberRootNode。
function FiberRootNode(containerInfo, tag, hydrate) { this.tag = tag; // 類型 this.containerInfo = containerInfo; // container this.pendingChildren = null; this.current = null; this.pingCache = null; this.finishedWork = null; this.timeoutHandle = noTimeout; this.context = null; this.pendingContext = null; this.hydrate = hydrate; this.callbackNode = null; this.callbackPriority = NoLanePriority; this.eventTimes = createLaneMap(NoLanes); this.expirationTimes = createLaneMap(NoTimestamp); this.pendingLanes = NoLanes; this.suspendedLanes = NoLanes; this.pingedLanes = NoLanes; this.mutableReadLanes = NoLanes; this.finishedLanes = NoLanes; this.entangledLanes = NoLanes; this.entanglements = createLaneMap(NoLanes); // .... }
這里的tag,有以下幾種類型。
export type RootTag = 0 | 1;
上述的結(jié)構(gòu)是fiberRootNode節(jié)點。
rootTag 等于0 時,代表legacy渲染模式,等于1時,代表Concurrent mode渲染,也就是說,傳統(tǒng)我們使用React.render進行渲染,當(dāng)調(diào)用React.createRoot時,進入Concurrent mode渲染模式,即并行渲染。
現(xiàn)在我們一起看看fiber的結(jié)構(gòu)。
const uninitializedFiber = createHostRootFiber(tag, strictModeLevelOverride); root.current = uninitializedFiber; uninitializedFiber.stateNode = root;
uninitializedFiber為創(chuàng)建的FiberNode的創(chuàng)建的實例。
const createFiber = function( tag: WorkTag, pendingProps: mixed, key: null | string, mode: TypeOfMode, ): Fiber { // $FlowFixMe: the shapes are exact here but Flow doesn"t like constructors return new FiberNode(tag, pendingProps, key, mode); };
通過基礎(chǔ)的創(chuàng)建,生成FiberNode結(jié)構(gòu),如下
function FiberNode( tag: WorkTag, pendingProps: mixed, key: null | string, mode: TypeOfMode, ) { // Instance this.tag = tag;//組件類型 this.key = key;//key屬性 this.elementType = null;//元素類型,類函數(shù),顯示類,div顯示div this.type = null;//func或者class this.stateNode = null;//dom節(jié)點 // Fiber this.return = null;//指向父節(jié)點 this.child = null;//指向子節(jié)點 this.sibling = null;//兄弟節(jié)點 this.index = 0;// this.ref = null; this.pendingProps = pendingProps;//等待中的屬性pendingProps this.memoizedProps = null; //記憶屬性,一般存放props this.updateQueue = null;//更新隊列 this.memoizedState = null;// 一般存放state this.dependencies = null; this.mode = mode; // Effects相關(guān) this.flags = NoFlags; this.subtreeFlags = NoFlags; this.deletions = null; this.lanes = NoLanes; this.childLanes = NoLanes; this.alternate = null;//指向workInProgress }
FiberNode基本顯示如上,elementType和type的基礎(chǔ)類型為function、class。
通過對比fiberRootNode結(jié)構(gòu),和下面的代碼,生成最終的FiberNode 結(jié)構(gòu)。
render() { const { name, count } = this.state; return ( <div className="App"> <Button name={name} /> { count } </div> ); }
ReactDOM.render( <React.StrictMode> <App /> </React.StrictMode>, root );
通過最后執(zhí)行,生成fiberRoot鏈表結(jié)構(gòu)。
最后,調(diào)用unbatchedUpdates,進行渲染。
進入updateContainer函數(shù)。
unbatchedUpdates(() => { // 更新container updateContainer(children, fiberRoot, parentComponent, callback); });
三、結(jié)束
以上就是React Fiber結(jié)構(gòu)的創(chuàng)建步驟的詳細(xì)內(nèi)容,更多關(guān)于React Fiber結(jié)構(gòu)的創(chuàng)建的資料請關(guān)注服務(wù)器之家其它相關(guān)文章!
原文鏈接:https://juejin.cn/post/6950692243485229086