最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

React Fiber源碼深入分析

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

前言

本次React源碼參考版本為17.0.3。

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

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

React@15及之前

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

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

但是React團隊意識到這樣的架構(gòu)有致命問題: 因為在React15中,組件的更新是基于遞歸查找實現(xiàn)的,這樣一旦開始遞歸,是沒有辦法中斷的,如果組件層級很深,就會出現(xiàn)性能問題,導致頁面卡頓。

React@16及之后

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

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

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

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

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

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

  • 進入了更高優(yōu)先級的任務;
  • 瀏覽器在當前幀沒有剩余空閑時間了;

Fiber

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

Fiber簡單理解

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

假如有這樣一段代碼:

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

上面的代碼的抽象Fiber樹:

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

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

來看一個Fiber會有哪些屬性:

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)境對應dom節(jié)點
  this.return = null;       // 指向父節(jié)點
  this.child = null;        // 孩子節(jié)點
  this.sibling = null;      // 兄弟節(jié)點, 兄弟節(jié)點的return指向同一個父節(jié)點
  this.index = 0;
  this.ref = null;          // ref
  this.pendingProps = pendingProps;     // 新的props
  this.memoizedProps = null;        // 上一次渲染完成的props
  this.updateQueue = null;          // 組件產(chǎn)生的update信息會放在這個隊列
  this.memoizedState = null;        // // 上一次渲染完成的state
  this.dependencies = null;
  this.mode = mode; // Effects
  this.flags = NoFlags;     // 相當于之前的effectTag, 記錄side effect類型
  this.nextEffect = null;   // 單鏈表結(jié)構(gòu), 便于快速查找下一個side effect
  this.firstEffect = null;  // fiber中第一個side effect
  this.lastEffect = null;   // fiber中最后一個side effect
  this.lanes = NoLanes;     // 優(yōu)先級相關
  this.childLanes = NoLanes;  // 優(yōu)先級相關
  this.alternate = null;    // 對應的是current fiber
}

Fiber工作原理

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

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

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

mount

React代碼在第一次執(zhí)行時,因為頁面還沒有渲染出來,此時是沒有current樹的,只有一個正在構(gòu)建DOM的workInProgress樹。

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

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

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

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

  • fiberRoot:整個React應用的根節(jié)點;
  • rootFiber: 某個組件樹的根節(jié)點;(因為我們可能多次使用React.render()函數(shù),這樣就會有多個rootFiber)

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

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

update

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

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

相關文章

  • React router cache route實現(xiàn)緩存頁面流程介紹

    React router cache route實現(xiàn)緩存頁面流程介紹

    react-router自身沒有路由緩存的特性,在5.x版本之前,我們可以基于react-router-cache-route來實現(xiàn)路由緩存功能。但是react-router 6.x在實現(xiàn)上做了比較大的變化,react-router-cache-route沒有提供相應的支持
    2023-01-01
  • React錯誤邊界Error Boundaries

    React錯誤邊界Error Boundaries

    錯誤邊界是一種React組件,這種組件可以捕獲發(fā)生在其子組件樹任何位置的JavaScript錯誤,并打印這些錯誤,同時展示降級UI,而并不會渲染那些發(fā)生崩潰的子組件樹
    2023-01-01
  • 新建的React Native就遇到vscode報警解除方法

    新建的React Native就遇到vscode報警解除方法

    這篇文章主要為大家介紹了新建的React Native就遇到vscode報警解除方法詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-10-10
  • React聲明組件的方法總結(jié)

    React聲明組件的方法總結(jié)

    這篇文章主要給大家介紹了react聲明組件有哪幾種方法,各有什么不同,文章通過代碼示例介紹的非常詳細,對大家的學習或工作有一定的幫助,需要的朋友可以參考下
    2023-11-11
  • react-router4按需加載(踩坑填坑)

    react-router4按需加載(踩坑填坑)

    這篇文章主要介紹了react-router4按需加載(踩坑填坑),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2019-01-01
  • React中事件綁定的5種實現(xiàn)方式和優(yōu)劣對比全攻略

    React中事件綁定的5種實現(xiàn)方式和優(yōu)劣對比全攻略

    在React中,事件綁定不僅僅是把函數(shù)和元素連接起來那么簡單,它關系到很多方面,下面我們就來一起來看看React事件綁定的5種主要方式,以及它們各自的優(yōu)缺點吧
    2026-01-01
  • react如何實現(xiàn)表格多條件搜索

    react如何實現(xiàn)表格多條件搜索

    這篇文章主要介紹了react如何實現(xiàn)表格多條件搜索問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-03-03
  • react Input組件Compositionstart和Compositionend事件

    react Input組件Compositionstart和Compositionend事件

    這篇文章主要為大家介紹了Compositionstart和Compositionend事件之于react組件庫Input組件的坑解決,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-11-11
  • React中路由參數(shù)如何改變頁面不刷新數(shù)據(jù)的情況

    React中路由參數(shù)如何改變頁面不刷新數(shù)據(jù)的情況

    這篇文章主要介紹了React中路由參數(shù)如何改變頁面不刷新數(shù)據(jù)的情況,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-08-08
  • react build 后打包發(fā)布總結(jié)

    react build 后打包發(fā)布總結(jié)

    這篇文章主要介紹了react build 后打包發(fā)布總結(jié),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-08-08

最新評論

墨江| 东乡族自治县| 宜丰县| 泗水县| 双流县| 会东县| 延安市| 临夏县| 辽宁省| 宁河县| 星座| 金坛市| 志丹县| 铁岭县| 南郑县| 满洲里市| 家居| 临夏县| 汤原县| 灵璧县| 松滋市| 法库县| 沂源县| 洛隆县| 宜春市| 宝兴县| 通州区| 新竹市| 洛隆县| 娱乐| 芮城县| 普定县| 海门市| 咸宁市| 玛纳斯县| 连山| 平陆县| 英吉沙县| 辽宁省| 龙口市| 冀州市|