欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

React Fiber源碼深入分析

 更新時(shí)間:2022年11月04日 14:36:36   作者:goClient1992  
Fiber 可以理解為一個(gè)執(zhí)行單元,每次執(zhí)行完一個(gè)執(zhí)行單元,React Fiber就會(huì)檢查還剩多少時(shí)間,如果沒有時(shí)間則將控制權(quán)讓出去,然后由瀏覽器執(zhí)行渲染操作,這篇文章主要介紹了React Fiber架構(gòu)原理剖析,需要的朋友可以參考下

前言

本次React源碼參考版本為17.0.3

React架構(gòu)前世今生

查閱文檔了解到, React@16.x是個(gè)分水嶺。

React@15及之前

在16之前,React架構(gòu)大致可以分為兩層:

  • Reconciler: 主要職責(zé)是對比查找更新前后的變化的組件;
  • Renderer: 主要職責(zé)是基于變化渲染頁面;

但是React團(tuán)隊(duì)意識(shí)到這樣的架構(gòu)有致命問題: 因?yàn)樵赗eact15中,組件的更新是基于遞歸查找實(shí)現(xiàn)的,這樣一旦開始遞歸,是沒有辦法中斷的,如果組件層級(jí)很深,就會(huì)出現(xiàn)性能問題,導(dǎo)致頁面卡頓。

React@16及之后

為了解決這樣的問題,React團(tuán)隊(duì)在React@16進(jìn)行了重構(gòu),引入了新的架構(gòu)模型:

  • Reconciler: 主要職責(zé)是對比查找更新前后的變化的組件;
  • Renderer: 主要職責(zé)是基于變化渲染頁面;
  • Scheduler: 主要職責(zé)是區(qū)分任務(wù)優(yōu)先級(jí),優(yōu)先執(zhí)行高優(yōu)先級(jí)的任務(wù);

新的架構(gòu)在原來的基礎(chǔ)上引入了Scheduler(調(diào)度器),這個(gè)東西是React團(tuán)隊(duì)參考瀏覽器的API:requestIdleCallback實(shí)現(xiàn)的。它的主要作用就是調(diào)度更新任務(wù):

  • 一方面可以中斷當(dāng)前任務(wù)執(zhí)行更高優(yōu)先級(jí)的任務(wù);
  • 另一方面能判斷瀏覽器空閑時(shí)間,在恰當(dāng)?shù)臅r(shí)間將主動(dòng)權(quán)給到瀏覽器,保證頁面性能;并在瀏覽器下次空閑時(shí)繼續(xù)之前中斷的任務(wù); 這樣就將之前的不可中斷的同步更新變成了異步可中斷更新,不直接使用瀏覽器API可能考慮到兼容問題,可能也有別的方面的考量。

下面是新的React架構(gòu)更新模型:

這個(gè)新的架構(gòu)在進(jìn)入Renderer之前的流程是可以被中斷的,主要有下列兩種情況:

  • 進(jìn)入了更高優(yōu)先級(jí)的任務(wù);
  • 瀏覽器在當(dāng)前幀沒有剩余空閑時(shí)間了;

Fiber

Fiber簡單的理解就是React15版本的虛擬DOM。

Fiber簡單理解

如果將新的React架構(gòu)比作一個(gè)公司,F(xiàn)iber在新的架構(gòu)里承擔(dān)的就是這個(gè)公司的員工,員工也有等級(jí),老板,部長,基層,每個(gè)人有自己的職責(zé),知道自己在哪個(gè)節(jié)點(diǎn)該做什么工作,并將未完成的工作記住等第二天上班繼續(xù)完成,從而保證公司的順利運(yùn)行。而每個(gè)Fiber對應(yīng)一個(gè)React element

假如有這樣一段代碼:

function App() {
    return (
        <div>
            <span>牛牛</span>
            <span>不怕困難</span>
        </div>
     )
}

上面的代碼的抽象Fiber樹:

其中的每個(gè)方塊都是一個(gè)Fiber,它們通過child, return, sibling連接對方構(gòu)成一個(gè)Fiber樹。相關(guān)參考視頻講解:傳送門

Fiber結(jié)構(gòu)

來看一個(gè)Fiber會(huì)有哪些屬性:

function FiberNode(tag, pendingProps, key, mode) {
  // Instance
  this.tag = tag;   // 組件類型
  this.key = key;   // 組件props上的key
  this.elementType = null;      // ReactElement.type 組件的dom類型, 比如`div, p`
  this.type = null;     // 異步組件resolved之后返回的內(nèi)容
  this.stateNode = null; // 在瀏覽器環(huán)境對應(yīng)dom節(jié)點(diǎn)
  this.return = null;       // 指向父節(jié)點(diǎn)
  this.child = null;        // 孩子節(jié)點(diǎn)
  this.sibling = null;      // 兄弟節(jié)點(diǎn), 兄弟節(jié)點(diǎn)的return指向同一個(gè)父節(jié)點(diǎn)
  this.index = 0;
  this.ref = null;          // ref
  this.pendingProps = pendingProps;     // 新的props
  this.memoizedProps = null;        // 上一次渲染完成的props
  this.updateQueue = null;          // 組件產(chǎn)生的update信息會(huì)放在這個(gè)隊(duì)列
  this.memoizedState = null;        // // 上一次渲染完成的state
  this.dependencies = null;
  this.mode = mode; // Effects
  this.flags = NoFlags;     // 相當(dāng)于之前的effectTag, 記錄side effect類型
  this.nextEffect = null;   // 單鏈表結(jié)構(gòu), 便于快速查找下一個(gè)side effect
  this.firstEffect = null;  // fiber中第一個(gè)side effect
  this.lastEffect = null;   // fiber中最后一個(gè)side effect
  this.lanes = NoLanes;     // 優(yōu)先級(jí)相關(guān)
  this.childLanes = NoLanes;  // 優(yōu)先級(jí)相關(guān)
  this.alternate = null;    // 對應(yīng)的是current fiber
}

Fiber工作原理

在弄明白Fiber工作原理之前,我們要先明確一個(gè)認(rèn)知:新的React架構(gòu)使用了兩個(gè)Fiber樹。

  • 一個(gè)Fiber樹是當(dāng)前頁面dom的抽象,叫current
  • 另一個(gè)Fiber樹是在內(nèi)存中執(zhí)行更新任務(wù)dom的抽象,叫workInProgress;

這樣做是為了方便比對變化組件,并降低創(chuàng)建的成本,盡可能復(fù)用現(xiàn)有代碼邏輯,從而提高渲染效率。

mount

React代碼在第一次執(zhí)行時(shí),因?yàn)轫撁孢€沒有渲染出來,此時(shí)是沒有current樹的,只有一個(gè)正在構(gòu)建DOM的workInProgress樹。

假如我們有這樣一段代碼:

function App() {
    return (
        <div>
            <span>牛牛</span>
            <span>不怕困難</span>
        </div>
     )
}
ReactDOM.render(<App/>, document.querySelector('#root'));

基于上面的代碼在mount會(huì)生成這樣的Fiber樹:

可以看到這個(gè)圖只是在前面的圖上增加了fiberRootrootFiber兩個(gè)Fiber節(jié)點(diǎn)。

  • fiberRoot:整個(gè)React應(yīng)用的根節(jié)點(diǎn);
  • rootFiber: 某個(gè)組件樹的根節(jié)點(diǎn);(因?yàn)槲覀兛赡芏啻问褂?code>React.render()函數(shù),這樣就會(huì)有多個(gè)rootFiber)

圖中此時(shí)fiberRoot對應(yīng)的rootFiber下面還是空的,因?yàn)榇藭r(shí)是第一次渲染,頁面上沒有任何東西,當(dāng)workInProgress樹構(gòu)建完成,在mutation之后,layout之前,fiberRootd的current指針會(huì)指向workInProgress樹,把它作為新的current樹,此時(shí)結(jié)構(gòu)會(huì)變成這樣:

這時(shí)頁面渲染完成了,等待下次觸發(fā)更新時(shí)會(huì)從current樹進(jìn)行拷貝生成workInProgress樹,然后比對更新。

update

如果我們在上面的代碼中觸發(fā)更新,將牛牛文本改成了勇敢牛牛,React代碼就會(huì)開始進(jìn)行任務(wù)調(diào)度,因?yàn)橹挥羞@一個(gè)任務(wù),會(huì)馬上執(zhí)行,會(huì)從current樹的rootFiber進(jìn)行拷貝生成workInProgress樹的根節(jié)點(diǎn),在經(jīng)過向下遍歷比對,發(fā)現(xiàn)相同的就直接從current樹上拷貝復(fù)用,直到比對到葉子節(jié)點(diǎn)的牛牛文本變了,這時(shí)才會(huì)生成新的Fiber(這里只是為了方便解釋,其實(shí)我這里使用的代碼牛牛不會(huì)生成新的Fiber,因?yàn)槭羌兾谋?,只?huì)替換父級(jí)節(jié)點(diǎn)的props)

到此這篇關(guān)于React Fiber源碼深入分析的文章就介紹到這了,更多相關(guān)React Fiber內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 詳解React?hooks組件通信方法

    詳解React?hooks組件通信方法

    這篇文章主要介紹了React?hooks組件通信,在開發(fā)中組件通信是React中的一個(gè)重要的知識(shí)點(diǎn),本文通過實(shí)例代碼給大家講解react hooks中常用的父子、跨組件通信的方法,需要的朋友可以參考下
    2022-07-07
  • React新文檔切記不要濫用effect

    React新文檔切記不要濫用effect

    這篇文章主要為大家介紹了React新文檔濫用effect出現(xiàn)的問題詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-07-07
  • 使用React?SSR寫Demo一學(xué)就會(huì)

    使用React?SSR寫Demo一學(xué)就會(huì)

    這篇文章主要為大家介紹了使用React?SSR寫Demo實(shí)現(xiàn)教程示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-06-06
  • react中代碼塊輸出,代碼高亮顯示,帶行號(hào),能復(fù)制的問題

    react中代碼塊輸出,代碼高亮顯示,帶行號(hào),能復(fù)制的問題

    這篇文章主要介紹了react中代碼塊輸出,代碼高亮顯示,帶行號(hào),能復(fù)制的問題,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-09-09
  • 如何不使用eject修改create-react-app的配置

    如何不使用eject修改create-react-app的配置

    許多剛開始接觸create-react-app框架的同學(xué),不免都會(huì)有個(gè)疑問:如何在不執(zhí)行eject操作的同時(shí),修改create-react-app的配置。
    2021-04-04
  • 從零開始最小實(shí)現(xiàn)react服務(wù)器渲染詳解

    從零開始最小實(shí)現(xiàn)react服務(wù)器渲染詳解

    這篇文章主要介紹了從零開始最小實(shí)現(xiàn)react服務(wù)器渲染詳解,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-01-01
  • Redux thunk中間件及執(zhí)行原理詳細(xì)分析

    Redux thunk中間件及執(zhí)行原理詳細(xì)分析

    redux的核心概念其實(shí)很簡單:將需要修改的state都存入到store里,發(fā)起一個(gè)action用來描述發(fā)生了什么,用reducers描述action如何改變state tree,這篇文章主要介紹了Redux thunk中間件及執(zhí)行原理分析
    2022-09-09
  • React基于路由的代碼分割技術(shù)詳解

    React基于路由的代碼分割技術(shù)詳解

    這篇文章主要為大家介紹了React基于路由的代碼分割技術(shù)詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-12-12
  • ReactiveCocoa代碼實(shí)踐之-UI組件的RAC信號(hào)操作

    ReactiveCocoa代碼實(shí)踐之-UI組件的RAC信號(hào)操作

    這篇文章主要介紹了ReactiveCocoa代碼實(shí)踐之-UI組件的RAC信號(hào)操作 的相關(guān)資料,需要的朋友可以參考下
    2016-04-04
  • React路由跳轉(zhuǎn)的實(shí)現(xiàn)示例

    React路由跳轉(zhuǎn)的實(shí)現(xiàn)示例

    在React中,可以使用多種方法進(jìn)行路由跳轉(zhuǎn),本文主要介紹了React路由跳轉(zhuǎn)的實(shí)現(xiàn)示例,具有一定的參考價(jià)值,感興趣的可以了解一下
    2023-12-12

最新評(píng)論