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

react?fiber執(zhí)行原理示例解析

 更新時間:2022年11月03日 17:14:35   作者:六六全棧  
這篇文章主要為大家介紹了react?fiber執(zhí)行原理示例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪

為什么要使用fiber,要解決什么問題?

react16 引入 Fiber 架構之前,react 會采用遞歸方法對比兩顆虛擬DOM樹,找出需要改動的節(jié)點,然后同步更新它們,這個過程 react 稱為reconcilation(協(xié)調)。在reconcilation期間,react 會同步執(zhí)行操作,提交到真實 DOM 的更改,會一直占著瀏覽器的資源,不能中斷,中斷后就不能恢復,使得我們一些用戶操作定時器等等事件無法得到響應,是一個非常糟糕的用戶體驗。

所以我們要解決的問題就是:解決React主線程長時間占用的一個問題。 這個時候,就引入了Fiber架構。

fiber是什么?

Fiber 可以理解為是一個執(zhí)行單元,也可以理解為是一種數(shù)據(jù)結構。每一個React元素都對應一個fiber對象,我們先看看fiber中的屬性:

function FiberNode(
  tag: WorkTag,
  pendingProps: mixed,
  key: null | string,
  mode: TypeOfMode,
) {
  // 作為靜態(tài)數(shù)據(jù)結構的屬性
  this.tag = tag;	     // Fiber對應組件的類型 Function/Class/Host...
  this.key = key;	     // key屬性
  this.elementType = null;   // 大部分情況同type,某些情況不同,比如FunctionComponent使用React.memo包裹
  this.type = null;					// 對于 FunctionComponent,指函數(shù)本身,對于ClassComponent,指class,對于HostComponent,指DOM節(jié)點tagName
  this.stateNode = null;		// Fiber對應的真實DOM節(jié)點
  // 用于連接其他Fiber節(jié)點形成Fiber樹
  this.parent = null;		// 指向父級Fiber節(jié)點
  this.child = null;		// 指向子Fiber節(jié)點
  this.sibling = null;	// 指向右邊第一個兄弟Fiber節(jié)點
  this.index = 0;
  this.ref = null;
  // 作為動態(tài)的工作單元的屬性 —— 保存本次更新造成的狀態(tài)改變相關信息
  this.pendingProps = pendingProps;
  this.memoizedProps = null;
  this.updateQueue = null;		// class 組件 Fiber 節(jié)點上的多個 Update 會組成鏈表并被包含在 fiber.updateQueue 中。 函數(shù)組件則是存儲 useEffect 的 effect 的環(huán)狀鏈表。
  this.memoizedState = null;	// hook 組成單向鏈表掛載的位置
  this.dependencies = null;
  this.mode = mode;
  // Effects
  this.flags = NoFlags;
  this.subtreeFlags = NoFlags;
  this.deletions = null;
  // 調度優(yōu)先級相關
  this.lanes = NoLanes;
  this.childLanes = NoLanes;
  // 指向該fiber在另一次更新時對應的fiber
  this.alternate = null;
}

數(shù)據(jù)結構

React Fiber 就是采用鏈表實現(xiàn)的,主要就是通過以下這幾個屬性表示:

  this.parent = null;		// 指向父級Fiber節(jié)點
  this.child = null;		// 指向子Fiber節(jié)點
  this.sibling = null;	// 指向右邊第一個兄弟Fiber節(jié)點

假如我們要渲染下面這個元素樹:

<div>
    <h1>
        <p>
            <a></a>
        </p>
    </h1>
    <h2></h2>
</div>

我們看一下它的Fiber結構樹:

每個fiber元素都有這三個屬性,觀察上面圖發(fā)現(xiàn):

  • parent:指向父級Fiber節(jié)點:
  • child:指向子Fiber節(jié)點
  • sibling:指向右邊的兄弟節(jié)點

執(zhí)行單元

我們可以把每個fiber當做一個執(zhí)行單元,每次執(zhí)行完一個執(zhí)行單元。React會去檢測還剩多少時間,如果沒有時間就將控制權讓給瀏覽器,如果還有時間就去執(zhí)行下一個執(zhí)行單元。
這里就涉及到了一個問題,react如何和瀏覽器進行控制權的交接,瀏覽器何時空閑呢?。我們先來了解一下瀏覽器的工作:

瀏覽器工作:

在瀏覽器中,我們所看到的頁面是一幀一幀畫出來的,渲染的幀率與設備的刷新率保持一致。通常情況下,我們的設備都是60Hz,也就是說,1s屏幕會刷新60次。當每秒內(nèi)繪制的幀數(shù)(FPS)超過60時,頁面渲染是流暢的,當幀數(shù)小于60時,會明顯感受到卡頓。下面來看完整的一幀中,瀏覽器具體做了哪些事情:

  • 首先需要處理輸入事件,能夠讓用戶得到最早的反饋
  • 接下來是處理定時器,需要檢查定時器是否到時間,并執(zhí)行對應的回調
  • 接下來處理 Begin Frame(開始幀),即每一幀的事件,包括 window.resizescroll、media query change
  • 接下來執(zhí)行請求動畫幀 requestAnimationFrame(rAF),即在每次繪制之前,會執(zhí)行 rAF 回調
  • 緊接著進行 Layout 操作,包括計算布局和更新布局,即這個元素的樣式是怎樣的,它應該在頁面如何展示
  • 接著進行 Paint 操作,得到樹中每個節(jié)點的尺寸與位置等信息,瀏覽器針對每個元素進行內(nèi)容填充
  • 到這時以上的六個階段都已經(jīng)完成了,接下來處于空閑階段(Idle Peroid),可以在這時執(zhí)行 requestIdleCallback 里注冊的任務

這樣我們把工作單元的任務放到requestIdleCallback回調當中,如果瀏覽器處理完上述的任務(布局和繪制之后),還有盈余時間,這個時候就可以執(zhí)行我們的工作單元了。每次執(zhí)行完一個執(zhí)行單元。React會去檢測還剩多少時間,如果沒有時間就將控制權讓給瀏覽器。直至,React和瀏覽器通過合作式調度完美配合,實現(xiàn)高性能應用。

Fiber執(zhí)行原理

從根節(jié)點開始調度和渲染可以分為兩個階段:rendercommit。 先來了解下這幾個關鍵名詞:

workInProgress tree:

workInProgress 代表當前正在執(zhí)行更新的 Fiber 樹。在 setState或者渲染 后,會構建一顆 Fiber 樹,也就是 workInProgress tree

currentFiber tree:

首次渲染之后,React 會生成一個對應于 UI 渲染的 fiber 樹,稱之為 current 樹。在新一輪更新時 workInProgress tree 再重新構建,新workInProgress的節(jié)點通過 alternate 屬性和 currentFiber 的節(jié)點建立聯(lián)系。

Effects list:

effect list 可以理解為是一個存儲 effect 副作用列表容器。

render階段:

render階段中,會找到所有節(jié)點的變更,比如說節(jié)點新增,編輯,刪除等等。這些變更React稱之為副作用effect。在這個階段中,也可以認為是diff階段,主要就是對比currentFiber treeworkInProgress tree之間的差異,然后打上標記。

在這個階段,任務是可以終止的。React 可以根據(jù)當前可用的時間片處理一個或多個 fiber 節(jié)點,并且得益于 fiber 對象中存儲的元素上下文信息以及構成的鏈表結構,使其能夠將執(zhí)行到一半的工作仍保存在內(nèi)存的鏈表中。在重新獲得控制權后,又可以根據(jù)保存在內(nèi)存中的上下文信息快速找到停止的fiber節(jié)點,然后繼續(xù)工作執(zhí)行工作單元。

遍歷節(jié)點過程:

遍歷Fiber tree時采用的是后序遍歷方法

  • 從頂部開始遍歷
  • 如果有child節(jié)點,且還未遍歷,遍歷child節(jié)點
  • 如果有child節(jié)點,且已經(jīng)遍歷過,則遍歷sibling節(jié)點。
  • 如果沒有child節(jié)點,返回父節(jié)點
  • 如果最后返回的節(jié)點為頂部,表示所有節(jié)點遍歷完成。

收集effect list:

在遍歷的過程中,我們會去收集所有變更的節(jié)點產(chǎn)出的effect,每個effect通過鏈表的方式鏈接。每個 fiber 有兩個屬性

  • firstEffect:指向第一個有副作用的子fiber
  • lastEffect:指向最后一個有副作用的子fiber

中間的使用nextEffect做成一個單鏈表。

commit階段:

render階段不同,commit階段是同步操作的。

為什么commit必須是同步的操作的?

因為在commit階段是更新真實的dom,所以更新dom不可能一點一點去更新,這樣用戶體驗會極差。所以commit階段必須是同步執(zhí)行,一次更新到位。

首先的事情是遍歷effect-list列表,拿到每一個 effect 存儲的信息,根據(jù)副作用類型 effectTag 執(zhí)行相應的處理并提交更新到真正的 DOM。所有的effects都會在layout phase階段之前被處理。當該階段執(zhí)行結束時,workInProgress樹會被替換成current樹。到這里,根據(jù)收集到的變更信息完成了刷新操作。

以上就是react fiber執(zhí)行原理示例解析的詳細內(nèi)容,更多關于react fiber執(zhí)行原理的資料請關注腳本之家其它相關文章!

相關文章

  • Ant Design組件庫的使用教程

    Ant Design組件庫的使用教程

    AntDesign ,簡稱antd是基于 Ant Design 設計體系的 React UI 組件庫,主要用于研發(fā)企業(yè)級中后臺產(chǎn)品,這篇文章主要介紹了Ant Design組件庫的使用教程,需要的朋友可以參考下
    2023-12-12
  • React中引入less、less-loader問題

    React中引入less、less-loader問題

    這篇文章主要介紹了React中引入less、less-loader問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-01-01
  • 解決配置setupProxy.js代理,頁面報錯404問題

    解決配置setupProxy.js代理,頁面報錯404問題

    這篇文章主要介紹了解決配置setupProxy.js代理,頁面報錯404問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-07-07
  • React如何以Hook的方式使用Echarts

    React如何以Hook的方式使用Echarts

    這篇文章主要介紹了React如何以Hook的方式使用Echarts問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-03-03
  • react項目實踐之webpack-dev-serve

    react項目實踐之webpack-dev-serve

    這篇文章主要介紹了react項目實踐之webpack-dev-serve,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-09-09
  • 淺談React原生APP更新

    淺談React原生APP更新

    當一個APP在運行的時候, 開發(fā)者想要將自己的代碼更新到用戶的手機上時, 一般都有兩種方案, 一是熱更新, 二就是APP更新.熱更新暫且不說,這篇文章就講講 APP 如何更新。
    2021-06-06
  • React詳細講解JSX和組件的使用

    React詳細講解JSX和組件的使用

    jsx就是javsscript與xml結合的一種格式,是js語法的一種擴展,只要把html代碼寫在js中就是jsx。react中定義組件有3種寫法:函數(shù)的方式、es5的寫法、es6(類)的寫法
    2022-08-08
  • react+typescript中使用echarts的實現(xiàn)步驟

    react+typescript中使用echarts的實現(xiàn)步驟

    本文主要介紹了react+typescript中使用echarts的實現(xiàn)步驟,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2022-08-08
  • React 高階組件HOC用法歸納

    React 高階組件HOC用法歸納

    高階組件就是接受一個組件作為參數(shù)并返回一個新組件(功能增強的組件)的函數(shù)。這里需要注意高階組件是一個函數(shù),并不是組件,這一點一定要注意,本文給大家分享React 高階組件HOC使用小結,一起看看吧
    2021-06-06
  • react quill中圖片上傳由默認轉成base64改成上傳到服務器的方法

    react quill中圖片上傳由默認轉成base64改成上傳到服務器的方法

    這篇文章主要介紹了react quill中圖片上傳由默認轉成base64改成上傳到服務器的方法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2019-10-10

最新評論