React Fiber結(jié)構(gòu)的創(chuàng)建步驟
React Fiber的創(chuàng)建
當(dāng)前React版本基于V17.0.2版本,本篇主要介紹fiber結(jié)構(gòu)的創(chuàng)建。
一、開(kāi)始之前
個(gè)人理解,如有不對(duì),請(qǐng)指出。
首先需要配置好React的debugger開(kāi)發(fā)環(huán)境,入口在這里:github
執(zhí)行npm run i,安裝依賴,npm start運(yùn)行環(huán)境。
二、從React.render開(kāi)始
通過(guò)在項(xiàng)目入口處調(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一共做了兩件事情,一個(gè)是生成了fiberRoot,一個(gè)是調(diào)用updateContainer。
進(jìn)入legacyCreateRootFromDOMContainer函數(shù),查看如何生成fiberRoot。 在函數(shù)內(nèi)部,調(diào)用了createLegacyRoot,在這里區(qū)分了下,是否使用hydrate,如下:
return createLegacyRoot( container, shouldHydrate ? { hydrate: true, } : undefined, );
對(duì)于createLegacyRoot來(lái)說(shuō),是用來(lái)實(shí)例化ReactDOMLegacyRoot函數(shù)的,通過(guò)后續(xù)調(diào)用,終于進(jìn)入到root的生成,調(diào)用createRootImpl函數(shù),實(shí)例化root。
進(jìn)入createFiberRoot函數(shù),初始化FiberRootNode。
function FiberRootNode(containerInfo, tag, hydrate) { this.tag = tag; // 類(lèi)型 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,有以下幾種類(lèi)型。
export type RootTag = 0 | 1;
上述的結(jié)構(gòu)是fiberRootNode節(jié)點(diǎn)。
rootTag 等于0 時(shí),代表legacy渲染模式,等于1時(shí),代表Concurrent mode渲染,也就是說(shuō),傳統(tǒng)我們使用React.render進(jìn)行渲染,當(dāng)調(diào)用React.createRoot時(shí),進(jìn)入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)建的實(shí)例。
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); };
通過(guò)基礎(chǔ)的創(chuàng)建,生成FiberNode結(jié)構(gòu),如下
function FiberNode( tag: WorkTag, pendingProps: mixed, key: null | string, mode: TypeOfMode, ) { // Instance this.tag = tag;//組件類(lèi)型 this.key = key;//key屬性 this.elementType = null;//元素類(lèi)型,類(lèi)函數(shù),顯示類(lèi),div顯示div this.type = null;//func或者class this.stateNode = null;//dom節(jié)點(diǎn) // Fiber this.return = null;//指向父節(jié)點(diǎn) this.child = null;//指向子節(jié)點(diǎn) this.sibling = null;//兄弟節(jié)點(diǎn) this.index = 0;// this.ref = null; this.pendingProps = pendingProps;//等待中的屬性pendingProps this.memoizedProps = null; //記憶屬性,一般存放props this.updateQueue = null;//更新隊(duì)列 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ǔ)類(lèi)型為function、class。
通過(guò)對(duì)比f(wàn)iberRootNode結(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 );
通過(guò)最后執(zhí)行,生成fiberRoot鏈表結(jié)構(gòu)。
最后,調(diào)用unbatchedUpdates,進(jìn)行渲染。
進(jìn)入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)建的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
React?antd中setFieldsValu的簡(jiǎn)便使用示例代碼
form.setFieldsValue是antd?Form組件中的一個(gè)方法,用于動(dòng)態(tài)設(shè)置表單字段的值,它接受一個(gè)對(duì)象作為參數(shù),對(duì)象的鍵是表單字段的名稱,值是要設(shè)置的字段值,這篇文章主要介紹了React?antd中setFieldsValu的簡(jiǎn)便使用,需要的朋友可以參考下2023-08-08react-router JS 控制路由跳轉(zhuǎn)實(shí)例
這篇文章主要介紹了react-router JS 控制路由跳轉(zhuǎn)實(shí)例,react實(shí)現(xiàn)路由可以直接使用react-router。有興趣的可以了解一下2017-06-06React利用scheduler思想實(shí)現(xiàn)任務(wù)的打斷與恢復(fù)
這篇文章主要為大家詳細(xì)介紹了React如何利用scheduler思想實(shí)現(xiàn)任務(wù)的打斷與恢復(fù),文中的示例代碼講解詳細(xì),感興趣的小伙伴可以參考一下2024-03-03React render核心階段深入探究穿插scheduler與reconciler
這篇文章主要介紹了React render核心階段穿插scheduler與reconciler,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)吧2022-11-11React組件化的一些額外知識(shí)點(diǎn)補(bǔ)充
React是一個(gè)用于構(gòu)建用戶界面的JavaScript庫(kù),下面這篇文章主要給大家介紹了關(guān)于React組件化的一些額外知識(shí)點(diǎn),文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-10-10React-Hooks之useImperativeHandler使用介紹
這篇文章主要為大家介紹了React-Hooks之useImperativeHandler使用介紹,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-07-07JS中使用react-tooltip插件實(shí)現(xiàn)鼠標(biāo)懸浮顯示框
前段時(shí)間遇到的一個(gè)需求,要求鼠標(biāo)懸停顯示使用描述, 用到了react-tooltip插件,今天寫(xiě)一個(gè)總結(jié),感興趣的朋友跟隨小編一起看看吧2019-05-05Objects are not valid as a Rea
這篇文章主要為大家介紹了Objects are not valid as a React child報(bào)錯(cuò)解決方法詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-12-12