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

React超詳細講述Fiber的使用

 更新時間:2023年02月08日 08:52:58   作者:折桂懷橘  
在fiber出現(xiàn)之前,react的架構(gòu)體系只有協(xié)調(diào)器reconciler和渲染器render。當(dāng)前有新的update時,react會遞歸所有的vdom節(jié)點,如果dom節(jié)點過多,會導(dǎo)致其他事件影響滯后,造成卡頓。即之前的react版本無法中斷工作過程,一旦遞歸開始無法停留下來

Fiber

概念

JavaScript引擎和頁面渲染引擎兩個線程是互斥的,當(dāng)其中一個線程執(zhí)行時,另一個線程只能掛起等待

如果 JavaScript 線程長時間地占用了主線程,那么渲染層面的更新就不得不長時間地等待,界面長時間不更新,會導(dǎo)致頁面響應(yīng)度變差,用戶可能會感覺到卡頓

破解JavaScript中同步操作時間過長的方法其實很簡單——分片。

把一個耗時長的任務(wù)分成很多小片,每一個小片的運行時間很短,雖然總時間依然很長,但是在每個小片執(zhí)行完之后,都給其他任務(wù)一個執(zhí)行的機會,這樣唯一的線程就不會被獨占,其他任務(wù)依然有運行的機會。

React Fiber把更新過程碎片化,每執(zhí)行完一段更新過程,就把控制權(quán)交還給React負責(zé)任務(wù)協(xié)調(diào)的模塊,看看有沒有其他緊急任務(wù)要做,如果沒有就繼續(xù)去更新,如果有緊急任務(wù),那就去做緊急任務(wù)。

維護每一個分片的數(shù)據(jù)結(jié)構(gòu),就是Fiber。

一個 Fiber 代表一個工作單元。

在react中,主要做了以下的操作:

  • 為每個增加了優(yōu)先級,優(yōu)先級高的任務(wù)可以中斷低優(yōu)先級的任務(wù)。然后再重新,注意是重新執(zhí)行優(yōu)先級低的任務(wù)
  • 增加了異步任務(wù),調(diào)用requestIdleCallback api,瀏覽器空閑的時候執(zhí)行
  • dom diff樹變成了鏈表,一個dom對應(yīng)兩個fiber(一個鏈表),對應(yīng)兩個隊列,這都是為找到被中斷的任務(wù),重新執(zhí)行

從架構(gòu)角度來看,F(xiàn)iber 是對 React核心算法(即調(diào)和過程)的重寫

從編碼角度來看,F(xiàn)iber是 React內(nèi)部所定義的一種數(shù)據(jù)結(jié)構(gòu),它是 Fiber樹結(jié)構(gòu)的節(jié)點單位,也就是 React 16 新架構(gòu)下的虛擬DOM

結(jié)構(gòu)

type Fiber = {
  // 用于標記fiber的WorkTag類型,主要表示當(dāng)前fiber代表的組件類型如FunctionComponent、ClassComponent等
  tag: WorkTag,
  // ReactElement里面的key
  key: null | string,
  // ReactElement.type,調(diào)用`createElement`的第一個參數(shù)
  elementType: any,
  // The resolved function/class/ associated with this fiber.
  // 表示當(dāng)前代表的節(jié)點類型
  type: any,
  // 表示當(dāng)前FiberNode對應(yīng)的element組件實例
  stateNode: any,
  // 指向他在Fiber節(jié)點樹中的`parent`,用來在處理完這個節(jié)點之后向上返回
  return: Fiber | null,
  // 指向自己的第一個子節(jié)點
  child: Fiber | null,
  // 指向自己的兄弟結(jié)構(gòu),兄弟節(jié)點的return指向同一個父節(jié)點
  sibling: Fiber | null,
  index: number,
  ref: null | (((handle: mixed) => void) & { _stringRef: ?string }) | RefObject,
  // 當(dāng)前處理過程中的組件props對象
  pendingProps: any,
  // 上一次渲染完成之后的props
  memoizedProps: any,
  // 該Fiber對應(yīng)的組件產(chǎn)生的Update會存放在這個隊列里面
  updateQueue: UpdateQueue<any> | null,
  // 上一次渲染的時候的state
  memoizedState: any,
  // 一個列表,存放這個Fiber依賴的context
  firstContextDependency: ContextDependency<mixed> | null,
  mode: TypeOfMode,
  // Effect
  // 用來記錄Side Effect
  effectTag: SideEffectTag,
  // 單鏈表用來快速查找下一個side effect
  nextEffect: Fiber | null,
  // 子樹中第一個side effect
  firstEffect: Fiber | null,
  // 子樹中最后一個side effect
  lastEffect: Fiber | null,
  // 代表任務(wù)在未來的哪個時間點應(yīng)該被完成,之后版本改名為 lanes
  expirationTime: ExpirationTime,
  // 快速確定子樹中是否有不在等待的變化
  childExpirationTime: ExpirationTime,
  // fiber的版本池,即記錄fiber更新過程,便于恢復(fù)
  alternate: Fiber | null,
}

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

Fiber樹的遍歷是這樣發(fā)生的深度遍歷

開始:Fiber 從最上面的 React 元素開始遍歷,并為其創(chuàng)建一個 fiber 節(jié)點。

子節(jié)點:然后,它轉(zhuǎn)到子元素,為這個元素創(chuàng)建一個 fiber 節(jié)點。這樣繼續(xù)下去直到在沒有孩子

兄弟節(jié)點: 現(xiàn)在,它檢查是否有兄弟節(jié)點元素。如果有,它就遍歷兄弟節(jié)點元素,然后再到兄弟姐妹的葉子元素。

返回:如果沒有兄弟節(jié)點,那么它就返回到父節(jié)點。

window.requestIdleCallback()

該方法將在瀏覽器的空閑時段內(nèi)調(diào)用的函數(shù)排隊。方法提供 deadline,即任務(wù)執(zhí)行限制時間,以切分任務(wù),避免長時間執(zhí)行,阻塞UI渲染而導(dǎo)致掉幀;

【安排低優(yōu)先級或非必要的函數(shù)在幀結(jié)束時的空閑時間被調(diào)用】

requestAnimationFrame

安排高優(yōu)先級的函數(shù)在下一個動畫幀之前被調(diào)用

Fiber是如何工作的

  • ReactDOM.render() 和 setState 的時候開始創(chuàng)建更新。
  • 將創(chuàng)建的更新加入任務(wù)隊列,等待調(diào)度。
  • 在 requestIdleCallback 空閑時執(zhí)行任務(wù)。
  • 從根節(jié)點開始遍歷 Fiber Node,并且構(gòu)建 WokeInProgress Tree。
  • 生成 effectList。
  • 根據(jù) EffectList 更新 DOM。

當(dāng)調(diào)用render和setState方法進行組件渲染和更新的時候,react會經(jīng)歷倆個階段:reconciler和render階段:

  • 調(diào)和階段(Reconciler):官方解釋。React 會自頂向下通過遞歸,遍歷新數(shù)據(jù)生成新的 Virtual DOM,然后通過 Diff 算法,找到需要變更的元素(Patch),放到更新隊列里面去。
  • 渲染階段(Renderer):遍歷更新隊列,通過調(diào)用宿主環(huán)境的API,實際更新渲染對應(yīng)元素。宿主環(huán)境,比如 DOM、Native、WebGL 等。

React15 最大的問題就是,Reconciler(協(xié)調(diào))階段產(chǎn)生產(chǎn)生虛擬DOM是通過深度優(yōu)先遞歸的,并且中途不可間斷。所以假如虛擬DOM很深的話,由于 JS線程和瀏覽器 GUI 線程是互斥的,處理 js 的時間過長,會導(dǎo)致瀏覽器刷新的時候掉幀,造成卡頓。

而 React16則實現(xiàn)了異步的可中斷的更新。

Fiber 使用 requestAnimationFrame 來處理優(yōu)先級較高的更新,使用 requestIdleCallback 處理優(yōu)先級較低的更新。因此,在調(diào)度工作時,F(xiàn)iber 檢查當(dāng)前更新的優(yōu)先級和 deadline (幀結(jié)束后的自由時間)。

如果優(yōu)先級高于待處理的工作,或者沒有 截止日期 或者截止日期尚未到達,F(xiàn)iber 可以在一幀之后安排多個工作單元。而下一組工作單元會被帶到更多的幀上。這就是使 Fiber 有可能暫停、重用和中止工作單元的原因。

那么,讓我們看看在預(yù)定的工作中實際發(fā)生了什么。有兩個階段來完成工作。render 和 commit。

渲染階段

實際的樹形遍歷和 deadline 的使用發(fā)生在這個階段。這是 Fiber 的內(nèi)部邏輯,所以在這個階段對 Fiber 樹所做的改變對用戶來說是不可見的。因此,F(xiàn)iber 可以暫停、中止或分擔(dān)多個框架的工作。

我們可以把這個階段稱為協(xié)調(diào)階段。 fiber 從 fiber 樹的根部開始遍歷,處理每個 fiber 。每一個工作單位都會調(diào)用workLoop 函數(shù)來執(zhí)行工作。我們可以把這個工作的處理分成兩個步驟。begin 和 complete 。

開始階段

如果你從 React 代碼庫中找到 workLoop 函數(shù),它就會調(diào)用 performUnitOfWork,它把 nextUnitOfWork 作為一個參數(shù),它就只是個工作的單位,將被執(zhí)行。 performUnitOfWork 函數(shù)內(nèi)部調(diào)用 beginWork 函數(shù)。這是 fiber 上發(fā)生實際工作的地方,而 performUnitOfWork 只是發(fā)生迭代的地方。

在 beginWork 函數(shù)中,如果 fiber 沒有任何待處理的工作,它就會直接跳出(跳過) fiber 而不進入開始階段。這就是在遍歷大樹時, fiber 跳過已經(jīng)處理過的 fiber ,直接跳到有待處理工作的 fiber 。如果你看到大的 beginWork 函數(shù)代碼塊,我們會發(fā)現(xiàn)一個開關(guān)塊,根據(jù) fiber 標簽,調(diào)用相應(yīng)的 fiber 更新函數(shù)。就像 updateHostComponent 用于宿主組件。這些函數(shù)會更新 fiber 。

如果有子 fiber ,beginWork函數(shù)返回子 fiber ,如果沒有子 fiber 則返回空。函數(shù) performUnitOfWork 持續(xù)迭代并調(diào)用子 fiber ,直到葉節(jié)點到達。在葉子節(jié)點的情況下,beginWork 返回 null,因為沒有任何子節(jié)點,performUnitOfWork 函數(shù)調(diào)用 completeUnitOfWork 函數(shù)?,F(xiàn)在讓我們看看完善階段。

完善階段

這個 completeUnitOfWork 函數(shù)通過調(diào)用一個 completeWork 函數(shù)來完成當(dāng)前單位的工作。如果有的話,completeUnitOfWork 會返回一個同級的 fiber 來執(zhí)行下一個工作單元,如果沒有工作的話,則會完成 return(parent) fiber 。這將一直持續(xù)到返回值為空,也就是說,直到它到達根節(jié)點。和 beginWork 一樣,completeWork 也是一個發(fā)生實際工作的函數(shù),而 completeUnitOfWork 是用于迭代的。

渲染階段的結(jié)果會產(chǎn)生一個效果列表(副作用)。這些效果就像插入、更新或刪除宿主組件的節(jié)點,或調(diào)用類組件節(jié)點的生命周期方法。這些 fiber 被標記為各自的效果標簽。

在渲染階段之后,F(xiàn)iber 將準備提交更新。

提交階段

這是一個階段,完成的工作將被用來在用戶界面上渲染它。由于這一階段的結(jié)果對用戶來說是可見的,所以不能被分成部分渲染。這個階段是一個同步的階段。

在這個階段的開始,F(xiàn)iber 有已經(jīng)在 UI 上渲染的 current 樹,finishedWork,或者在渲染階段建立的 workInProgress 樹和效果列表。

effect 列表是 fiber 的鏈表,它有副作用。所以,它是渲染階段的 workInProgress 樹的節(jié)點的一個子集,它有副作用(更新)。effect 列表的節(jié)點是用 nextEffect 指針鏈接的。

在這個階段調(diào)用的函數(shù)是 completeRoot。

在這里,workInProgress 樹成為 current 樹,因為它被用來渲染 UI。實際的 DOM 更新,如插入、更新、刪除,以及對生命周期方法的調(diào)用或者更新相對應(yīng)的引用 —— 發(fā)生在 effect 列表中的節(jié)點上。

這就是 fiber 協(xié)調(diào)器的工作方式。

結(jié)論

這就是 React Fiber 協(xié)調(diào)器使之有可能將工作分為多個工作單元。它設(shè)置每個工作的優(yōu)先級,并使暫停、重用和中止工作單元成為可能。在 fiber 樹中,單個節(jié)點保持跟蹤,這是使上述事情成為可能的需要。每個 fiber 都是一個鏈表的節(jié)點,它們通過子、兄弟節(jié)點和返回引用連接起來。

  • 有react fiber,為什么不需要vue fiber “我們現(xiàn)在已經(jīng)知道了react fiber是在彌補更新時“無腦”刷新,不夠精確帶來的缺陷。”fiber不是用來彌補無腦刷新的,fibe是用來讓原來同步的調(diào)用顆粒化的,解決無腦刷新你應(yīng)該用meno
  • vue不需要fiber是因為他使用nextTick來異步?jīng)Q定什么時候執(zhí)行renderfunction 本質(zhì)上思路是和react一致的和響應(yīng)式原理沒有半毛錢關(guān)系

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

相關(guān)文章

  • ReactNative踩坑之配置調(diào)試端口的解決方法

    ReactNative踩坑之配置調(diào)試端口的解決方法

    本篇文章主要介紹了ReactNative踩坑之配置調(diào)試端口的解決方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-07-07
  • 淺談react路由傳參的幾種方式

    淺談react路由傳參的幾種方式

    這篇文章主要介紹了淺談react路由傳參的幾種方式,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-03-03
  • 詳解React-Native全球化多語言切換工具庫react-native-i18n

    詳解React-Native全球化多語言切換工具庫react-native-i18n

    這篇文章主要介紹了詳解React-Native全球化語言切換工具庫react-native-i18n,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-11-11
  • React中的頁面跳轉(zhuǎn)方式示例詳解

    React中的頁面跳轉(zhuǎn)方式示例詳解

    React Router提供了幾種不同的跳轉(zhuǎn)方式,包括使用組件進行頁面跳轉(zhuǎn)、使用組件進行重定向,以及使用編程式導(dǎo)航進行跳轉(zhuǎn),這篇文章主要介紹了React中的頁面跳轉(zhuǎn)方式詳解,需要的朋友可以參考下
    2023-09-09
  • React中嵌入多個組件的多種方式詳解

    React中嵌入多個組件的多種方式詳解

    在 React 中,嵌入和使用多個組件是構(gòu)建用戶界面的核心機制,React 鼓勵組件化開發(fā),允許將 UI 拆分為獨立、可復(fù)用的部分,以下是實現(xiàn)多個組件嵌套和使用的常見方法,需要的朋友可以參考下
    2025-08-08
  • React入門教程之Hello World以及環(huán)境搭建詳解

    React入門教程之Hello World以及環(huán)境搭建詳解

    Facebook 為了開發(fā)一套更好更適合自己的JavaScript MVC 框架,所以產(chǎn)生了react。后來反響很好,所以于2013年5月開源。下面這篇文章主要給大家介紹了關(guān)于React入門教程之Hello World以及環(huán)境搭建的相關(guān)資料,需要的朋友可以參考借鑒。
    2017-07-07
  • 解決React報錯Invalid hook call

    解決React報錯Invalid hook call

    這篇文章主要為大家介紹了React報錯Invalid hook call解決方法詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-12-12
  • 官方推薦react-navigation的具體使用詳解

    官方推薦react-navigation的具體使用詳解

    本篇文章主要介紹了官方推薦react-navigation的具體使用詳解,react-navigation是致力于解決導(dǎo)航卡頓,數(shù)據(jù)傳遞,Tabbar和navigator布局,支持redux。非常具有實用價值,需要的朋友可以參考下
    2018-05-05
  • React?Native集成支付寶支付的實現(xiàn)方法

    React?Native集成支付寶支付的實現(xiàn)方法

    這篇文章主要介紹了React?Native集成支付寶支付的實現(xiàn)現(xiàn),ativeModules是JS代碼調(diào)用原生模塊的橋梁。所以,我們只需要在原生工程中集成支付寶和微信支付的sdk,然后使用NativeModules調(diào)用即可,需要的朋友可以參考下
    2022-02-02
  • React類組件和函數(shù)組件對比-Hooks的簡介

    React類組件和函數(shù)組件對比-Hooks的簡介

    Hook?是?React?16.8?的新增特性,它可以讓我們在不編寫class的情況下,?使用state以及其他的React特性(比如生命周期,這篇文章主要介紹了React類組件和函數(shù)組件對比-Hooks的介紹及初體驗,需要的朋友可以參考下
    2022-11-11

最新評論

霞浦县| 满城县| 霍邱县| 达州市| 博罗县| 湛江市| 芦溪县| 邢台市| 罗甸县| 克拉玛依市| 海伦市| 南乐县| 靖远县| 华宁县| 合作市| 闽清县| 贵溪市| 建宁县| 项城市| 荔浦县| 合川市| 红安县| 佛教| 武川县| 乌什县| 巴彦县| 新绛县| 苏尼特右旗| 孝昌县| 邮箱| 云南省| 顺昌县| 巫山县| 哈尔滨市| 金乡县| 葫芦岛市| 射阳县| 惠州市| 贺兰县| 定南县| 韶山市|