亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

React超詳細講述Fiber的使用

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

Fiber

概念

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

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

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

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

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

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

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

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

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

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

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

結構

type Fiber = {
  // 用于標記fiber的WorkTag類型,主要表示當前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.
  // 表示當前代表的節(jié)點類型
  type: any,
  // 表示當前FiberNode對應的element組件實例
  stateNode: any,
  // 指向他在Fiber節(jié)點樹中的`parent`,用來在處理完這個節(jié)點之后向上返回
  return: Fiber | null,
  // 指向自己的第一個子節(jié)點
  child: Fiber | null,
  // 指向自己的兄弟結構,兄弟節(jié)點的return指向同一個父節(jié)點
  sibling: Fiber | null,
  index: number,
  ref: null | (((handle: mixed) => void) & { _stringRef: ?string }) | RefObject,
  // 當前處理過程中的組件props對象
  pendingProps: any,
  // 上一次渲染完成之后的props
  memoizedProps: any,
  // 該Fiber對應的組件產(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,
  // 代表任務在未來的哪個時間點應該被完成,之后版本改名為 lanes
  expirationTime: ExpirationTime,
  // 快速確定子樹中是否有不在等待的變化
  childExpirationTime: ExpirationTime,
  // fiber的版本池,即記錄fiber更新過程,便于恢復
  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,即任務執(zhí)行限制時間,以切分任務,避免長時間執(zhí)行,阻塞UI渲染而導致掉幀;

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

requestAnimationFrame

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

Fiber是如何工作的

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

當調(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,實際更新渲染對應元素。宿主環(huán)境,比如 DOM、Native、WebGL 等。

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

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

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

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

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

渲染階段

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

我們可以把這個階段稱為協(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)一個開關塊,根據(jù) fiber 標簽,調(diào)用相應的 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ù)來完成當前單位的工作。如果有的話,completeUnitOfWork 會返回一個同級的 fiber 來執(zhí)行下一個工作單元,如果沒有工作的話,則會完成 return(parent) fiber 。這將一直持續(xù)到返回值為空,也就是說,直到它到達根節(jié)點。和 beginWork 一樣,completeWork 也是一個發(fā)生實際工作的函數(shù),而 completeUnitOfWork 是用于迭代的。

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

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

提交階段

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

在這個階段的開始,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)用或者更新相對應的引用 —— 發(fā)生在 effect 列表中的節(jié)點上。

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

結論

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

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

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

相關文章

  • React中的Hooks路由跳轉(zhuǎn)問題

    React中的Hooks路由跳轉(zhuǎn)問題

    這篇文章主要介紹了React中的Hooks路由跳轉(zhuǎn)問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-12-12
  • 在React項目中添加吸頂效果的代碼示例

    在React項目中添加吸頂效果的代碼示例

    在大型Web應用中,一個常見的設計需求是讓某些組件具有吸頂效果,這意味著當頁面向下滾動時,該組件會保持在屏幕頂部,在本文中,我們將介紹如何在React項目中實現(xiàn)吸頂效果。我們將首先討論使用原生JavaScript領域的方法來實現(xiàn),然后將這些方法與React結合起來
    2023-06-06
  • React學習筆記之高階組件應用

    React學習筆記之高階組件應用

    這篇文章主要介紹了React 高階組件應用,詳細的介紹了什么是React高階組件和具體使用,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-06-06
  • react實現(xiàn)移動端二級路由嵌套詳解

    react實現(xiàn)移動端二級路由嵌套詳解

    這篇文章主要介紹了react移動端二級路由嵌套的實現(xiàn)方法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2022-08-08
  • React useImperativeHandle處理組件狀態(tài)和生命周期用法詳解

    React useImperativeHandle處理組件狀態(tài)和生命周期用法詳解

    React Hooks 為我們提供了一種全新的方式來處理組件的狀態(tài)和生命周期,useImperativeHandle是一個相對較少被提及的Hook,但在某些場景下,它是非常有用的,本文將深討useImperativeHandle的用法,并通過實例來加深理解
    2023-09-09
  • 使用Node搭建reactSSR服務端渲染架構

    使用Node搭建reactSSR服務端渲染架構

    這篇文章主要介紹了使用Node搭建reactSSR服務端渲染架構,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-08-08
  • 每天一個hooks學習之useUnmount

    每天一個hooks學習之useUnmount

    這篇文章主要為大家介紹了每天一個hooks學習之useUnmount,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-05-05
  • React useCallback鉤子的作用方法demo

    React useCallback鉤子的作用方法demo

    這篇文章主要為大家介紹了React useCallback鉤子的作用方法demo,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-12-12
  • React編程中需要注意的兩個錯誤

    React編程中需要注意的兩個錯誤

    React可以說是前端的先驅(qū)者,它總是會引領整個前端的潮流。 但我們在使用也經(jīng)常會遇到錯誤,下面這篇文章主要給大家介紹了關于React編程中需要注意的兩個錯誤,需要的朋友可以參考下
    2021-05-05
  • 詳解React native全局變量的使用(跨組件的通信)

    詳解React native全局變量的使用(跨組件的通信)

    本篇文章主要介紹了詳解React native全局變量的使用(跨組件的通信),具有一定的參考價值,有興趣的同學可以了解一下
    2017-09-09

最新評論