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

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

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

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

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

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

fiber是什么?

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

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

數(shù)據(jù)結(jié)構(gòu)

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

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

假如我們要渲染下面這個(gè)元素樹:

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

我們看一下它的Fiber結(jié)構(gòu)樹:

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

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

執(zhí)行單元

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

瀏覽器工作:

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

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

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

Fiber執(zhí)行原理

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

workInProgress tree:

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

currentFiber tree:

首次渲染之后,React 會(huì)生成一個(gè)對(duì)應(yīng)于 UI 渲染的 fiber 樹,稱之為 current 樹。在新一輪更新時(shí) workInProgress tree 再重新構(gòu)建,新workInProgress的節(jié)點(diǎn)通過 alternate 屬性和 currentFiber 的節(jié)點(diǎn)建立聯(lián)系。

Effects list:

effect list 可以理解為是一個(gè)存儲(chǔ) effect 副作用列表容器。

render階段:

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

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

遍歷節(jié)點(diǎn)過程:

遍歷Fiber tree時(shí)采用的是后序遍歷方法

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

收集effect list:

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

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

中間的使用nextEffect做成一個(gè)單鏈表。

commit階段:

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

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

因?yàn)樵?code>commit階段是更新真實(shí)的dom,所以更新dom不可能一點(diǎn)一點(diǎn)去更新,這樣用戶體驗(yàn)會(huì)極差。所以commit階段必須是同步執(zhí)行,一次更新到位。

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

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

相關(guān)文章

  • 如何在React項(xiàng)目中使用AntDesign

    如何在React項(xiàng)目中使用AntDesign

    我們?cè)诤笈_(tái)管理系統(tǒng)React項(xiàng)目開發(fā)中會(huì)有Table表格、Form表單、List列表、Button按鈕等組件,這個(gè)時(shí)候我們可以使用AntDesign來減少開發(fā)中不必要的樣式問題,本文就介紹了eact項(xiàng)目中使用AntDesign,感興趣的可以了解一下
    2022-04-04
  • React中代碼分割的4種實(shí)現(xiàn)方式

    React中代碼分割的4種實(shí)現(xiàn)方式

    雖然一直有做react相關(guān)的優(yōu)化,按需加載、dll 分離、服務(wù)端渲染,但是從來沒有從路由代碼分割這一塊入手過,所以下面這篇文章主要給大家介紹了關(guān)于React中代碼分割的4種實(shí)現(xiàn)方式,需要的朋友可以參考下
    2022-01-01
  • 使用React+SpringBoot開發(fā)一個(gè)協(xié)同編輯的表格文檔實(shí)現(xiàn)步驟

    使用React+SpringBoot開發(fā)一個(gè)協(xié)同編輯的表格文檔實(shí)現(xiàn)步驟

    隨著云計(jì)算和團(tuán)隊(duì)協(xié)作的興起,協(xié)同編輯成為了許多企業(yè)和組織中必不可少的需求,本文小編就將為大家介紹如何使用React+SpringBoot簡單的開發(fā)一個(gè)協(xié)同編輯的表格文檔,感興趣的朋友一起看看吧
    2023-11-11
  • React中常用的一些鉤子函數(shù)總結(jié)

    React中常用的一些鉤子函數(shù)總結(jié)

    這篇文章給大家總結(jié)了React中常用的一些鉤子函數(shù),文中通過代碼示例給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下
    2024-01-01
  • react-native動(dòng)態(tài)切換tab組件的方法

    react-native動(dòng)態(tài)切換tab組件的方法

    在APP中免不了要使用tab組件,有的是tab切換,也有的是tab分類切換.這篇文章主要介紹了react-native動(dòng)態(tài)切換tab組件的方法,非常具有實(shí)用價(jià)值,需要的朋友可以參考下
    2018-07-07
  • React路由規(guī)則定義與聲明式導(dǎo)航及編程式導(dǎo)航分別介紹

    React路由規(guī)則定義與聲明式導(dǎo)航及編程式導(dǎo)航分別介紹

    這篇文章主要介紹了React路由規(guī)則的定義、聲明式導(dǎo)航、編程式導(dǎo)航,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧
    2022-09-09
  • react-player實(shí)現(xiàn)視頻播放與自定義進(jìn)度條效果

    react-player實(shí)現(xiàn)視頻播放與自定義進(jìn)度條效果

    本篇文章通過完整的代碼給大家介紹了react-player實(shí)現(xiàn)視頻播放與自定義進(jìn)度條效果,代碼簡單易懂,對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧
    2022-01-01
  • react-intl實(shí)現(xiàn)React國際化多語言的方法

    react-intl實(shí)現(xiàn)React國際化多語言的方法

    這篇文章主要介紹了react-intl實(shí)現(xiàn)React國際化多語言的方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-09-09
  • React降級(jí)配置及Ant Design配置詳解

    React降級(jí)配置及Ant Design配置詳解

    這篇文章主要介紹了React降級(jí)配置及Ant Design配置詳解,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-12-12
  • React antd tabs切換造成子組件重復(fù)刷新

    React antd tabs切換造成子組件重復(fù)刷新

    這篇文章主要介紹了React antd tabs切換造成子組件重復(fù)刷新,需要的朋友可以參考下
    2021-04-04

最新評(píng)論

芮城县| 崇阳县| 南涧| 敖汉旗| 峨眉山市| 大渡口区| 乐业县| 庆阳市| 上饶市| 东光县| 神木县| 四子王旗| 泸溪县| 深泽县| 明水县| 德钦县| 榆社县| 芮城县| 衢州市| 赤城县| 德兴市| 灵丘县| 喀喇| 通州区| 蕲春县| 南雄市| 公主岭市| 阳山县| 新竹市| 新民市| 巴彦淖尔市| 四子王旗| 莱西市| 景德镇市| 永泰县| 磴口县| 新丰县| 五家渠市| 佛坪县| 安顺市| 浦东新区|