摘要:在中調(diào)用獲得了的實例,然后調(diào)用其中的回調(diào)函數(shù)中調(diào)用了方法。這個類主要介紹其構(gòu)造函數(shù)和方法,構(gòu)造函數(shù)是時調(diào)用的,方法是的回調(diào)函數(shù)中使用的。這個將在下一篇分析。另外,方法是在的回調(diào)函數(shù)中調(diào)用的,也是一個參與后面調(diào)度的關(guān)鍵。
在ReactDOM.render源碼解析-1中介紹了第一次render的基本過程的一部分,其中產(chǎn)生了ReactRoot和ReactWork兩個類的實例。本文介紹下ReactRoot,ReactWork源碼,只關(guān)注第一次調(diào)用render的過程。回顧
文章中如有不當(dāng)之處,歡迎交流指點。react版本16.8.2。在源碼添加的注釋在githubreact-source-learn。
在上篇分析后,最終得到如下函數(shù)調(diào)用過程。
在render方法中調(diào)用了legacyRenderSubtreeIntoContainer。
在legacyRenderSubtreeIntoContainer中調(diào)用legacyCreateRootFromDOMContainer獲得了ReactRoot的實例root,然后調(diào)用unbatchedUpdates,其中的回調(diào)函數(shù)中調(diào)用了root.render方法。RootRoot是什么?他的render方法做了什么?
代碼分析通過對ReactRoot和ReactWork代碼的簡單分析,筆者做了如下類圖,以幫助了解這兩個類有哪些屬性和方法。
有很多東西不是第一次調(diào)用render用到的,這里只關(guān)注第一次render所需要調(diào)用方法或使用的屬性。
ReactRoot這個類主要介紹其構(gòu)造函數(shù)和render方法,構(gòu)造函數(shù)是new時調(diào)用的,render方法是unbatchedUpdates的回調(diào)函數(shù)中使用的。代碼如下:
// ReactRoot構(gòu)造函數(shù) // 構(gòu)造函數(shù)主要是掛了一個_internalRoot在this上 function ReactRoot( container: DOMContainer, // dom節(jié)點 isConcurrent: boolean, // 第一次render為false hydrate: boolean, // 第一次render為false ) { // 這個createContainer是packages/ReactFiberReconciler中的方法, // 返回的是一個OpaqueRoot的東西 const root = createContainer(container, isConcurrent, hydrate); this._internalRoot = root; } // render實例方法 new 了ReactWork, 調(diào)用了then方法 // 調(diào)用了updateContainer方法 // 返回了ReactWork實例 ReactRoot.prototype.render = function( children: ReactNodeList, // element callback: ?() => mixed, // ReactDOM.render(element, container, callback); callback ): Work { const root = this._internalRoot; const work = new ReactWork(); callback = callback === undefined ? null : callback; if (callback !== null) { work.then(callback); } // updateContainer是packages/react-reconciler/ReactFiberReconciler.js中的 // 一個方法,后邊再說 updateContainer(children, root, null, work._onCommit); return work; };
先看構(gòu)造函數(shù)
第一次render時new ReactRoot位于legacyCreateRootFromDOMContainer中,其調(diào)用代碼如下:
return new ReactRoot(container, isConcurrent, shouldHydrate)。
container是我們調(diào)用ReactDOM.render時的第二個參數(shù),一個dom,但是里邊的子節(jié)點已被處理了,isConcurrent這里是寫死的false,shouldHydrate上文分析過,為false。
再看ReactRoot的構(gòu)造函數(shù),他調(diào)用了一個createContainer并將返回值掛到了_internalRoot屬性。這個createContainer將在下一篇分析。
看下render方法
我們先看看第一次render是調(diào)用他的代碼,root.render(children, callback);,其中children是ReactDOM.render的第一個參數(shù),是個ReactElement, callback是第三個參數(shù),通常不傳。
這個render方法主要做了如下事:
new ReactWork -> work
調(diào)用work的then方法
調(diào)用updateContainer
返回work
這里值得注意的是ReactWork類,這個將在后文分析;還有updateContainer,這個將在后面的文章分析,這里搞清楚第一調(diào)用時的參數(shù)給的啥,即ReactElement,createContainer返回的root,null,ReactWork實例的_onCommit方法。
ReactWorkReactWork的方法在第一次render時都有可能被調(diào)用到,如下代碼為ReactWork類的定義:
// ReactWork的構(gòu)造函數(shù) function ReactWork() { this._callbacks = null; this._didCommit = false; // TODO: Avoid need to bind by replacing callbacks in the update queue with // list of Work objects. this._onCommit = this._onCommit.bind(this); } // then方法 ReactWork.prototype.then = function(onCommit: () => mixed): void { if (this._didCommit) { // 第一次render調(diào)用then時為false, 不走這里 onCommit(); return; } let callbacks = this._callbacks; if (callbacks === null) { // 第一次render是調(diào)用走這里 callbacks = this._callbacks = []; } callbacks.push(onCommit); }; // _onCommit方法 ReactWork.prototype._onCommit = function(): void { if (this._didCommit) { // 第一次render不走這里 return; } this._didCommit = true; // 這個callbacks是調(diào)用.then方法是傳進(jìn)去的函數(shù) const callbacks = this._callbacks; if (callbacks === null) { return; } // TODO: Error handling. for (let i = 0; i < callbacks.length; i++) { const callback = callbacks[i]; invariant( typeof callback === "function", "Invalid argument passed as callback. Expected a function. Instead " + "received: %s", callback, ); callback(); } };
構(gòu)造函數(shù)
構(gòu)造函數(shù)不接受參數(shù),做了一些初始化工作
then方法
then方法調(diào)用時是work.then(callback);,callback是ReactDOM的第三個參數(shù)
then方法的作用就是維護(hù)一個_callbacks隊列,每次都將傳進(jìn)去的函數(shù)入隊
_onCommit方法
這個方法的調(diào)用代碼updateContainer(children, root, null, work._onCommit),其實是updateContainer的最后一個參數(shù)。
在這個里邊將_didCommit置為true,回顧上邊的ReactRoot的render方法,意味著這個方法被調(diào)用后在調(diào)ReactRoot.render是會直接執(zhí)行callback的而不是入隊。
然后是將_callbacks中的方法都執(zhí)行了一遍。
從上文的分析來看,接下來的重點是分析updateContainer這個方法,ReactWork的then方法是將callback入隊,_onCommit是執(zhí)行_callbacks中的所有方法,而調(diào)用_onCommit的是在updateContainer中,updateContainer實在ReactRoot.render方法中調(diào)用的,因此updateContainer應(yīng)該是一個非常重要的東西。另外,ReactRoo.render方法是在unbatchedUpdates的回調(diào)函數(shù)中調(diào)用的,unbatchedUpdates也是一個參與后面調(diào)度的關(guān)鍵。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/103730.html
摘要:系列文章源碼分析第一篇源碼分析第二篇同步模式源碼分析第三篇異步狀態(tài)源碼分析第四篇歸納總結(jié)前言是在版本中的大更新,利用了閑余時間看了一些源碼,做個小記錄流程圖源碼分析先由編譯,調(diào)用,入?yún)?,打印出來可以看到,,分別代表著元素原生元素,回調(diào)函數(shù) 系列文章 React Fiber源碼分析 第一篇 React Fiber源碼分析 第二篇(同步模式) React Fiber源碼分析 第三篇(...
摘要:就是,如果你不了解這個的話可以閱讀下相關(guān)文檔,是應(yīng)用初始化時就會生成的一個變量,值也是,并且這個值不會在后期再被改變。這是我的剖析 React 源碼的第三篇文章,如果你沒有閱讀過之前的文章,請務(wù)必先閱讀一下 第一篇文章 中提到的一些注意事項,能幫助你更好地閱讀源碼。 文章相關(guān)資料 React 16.8.6 源碼中文注釋,這個鏈接是文章的核心,文中的具體代碼及代碼行數(shù)都是依托于這個倉庫 熱身...
摘要:本文將對源碼做一個初步解析。首先在方法中校驗參數(shù)是否合法,然后調(diào)用在中,調(diào)用拿到了的一個實例,調(diào)用拿到了,用于注入到,和作為返回值,調(diào)用開始調(diào)度過程在中,首先清理了中的所有子節(jié)點,然后了一個并返回是如何調(diào)度的是一個什么樣的類的操作是在哪里 初步看了react-dom這個包的一些源碼,發(fā)現(xiàn)其比react包要復(fù)雜得多,react包中基本不存在跨包調(diào)用的情況,他所做的也僅僅是定義了React...
摘要:查看創(chuàng)建核心函數(shù)源碼行調(diào)用函數(shù)創(chuàng)建是相關(guān),不用管源碼行這個指的是調(diào)用創(chuàng)建,下面我們將會說到對象源碼行源碼行函數(shù)中,首先創(chuàng)建了一個,然后又創(chuàng)建了一個,它們兩者還是相互引用。 感謝 yck: 剖析 React 源碼解析,本篇文章是在讀完他的文章的基礎(chǔ)上,將他的文章進(jìn)行拆解和加工,加入我自己的一下理解和例子,便于大家理解。覺得yck寫的真的很棒 。React 版本為 16.8.6,關(guān)于源碼的...
摘要:一更新的方式有三種渲染接下來,我們就來看下源碼二作用在提供的里渲染一個元素,并返回對該組件的引用常見的用法是這個官網(wǎng)網(wǎng)址源碼服務(wù)端使用方法渲染節(jié)點是讓服務(wù)端盡可能復(fù)用節(jié)點,提高性能元素容器應(yīng)用渲染結(jié)束后,調(diào)用的函數(shù)錯誤抓取方法本質(zhì)是返回 showImg(https://segmentfault.com/img/remote/1460000020064414?w=1240&h=641);...
閱讀 1414·2021-11-25 09:43
閱讀 2271·2021-09-27 13:36
閱讀 1124·2021-09-04 16:40
閱讀 1964·2019-08-30 11:12
閱讀 3320·2019-08-29 14:14
閱讀 575·2019-08-28 17:56
閱讀 1335·2019-08-26 13:50
閱讀 1257·2019-08-26 13:29