react如何實現hooks?必須依賴 Fiber 么?

react如何實現hooks?React Hooks 的實現必須依賴 Fiber 么?下面本篇文章帶大家來看看不同框架中的 hooks 都是怎么實現的 , 希望對大家有所幫助!

react如何實現hooks?必須依賴 Fiber 么?

文章插圖

React 的 hooks 是在 fiber 之后出現的特性 , 所以很多人誤以為 hooks 是必須依賴 fiber 才能實現的 , 其實并不是 , 它們倆沒啥必然聯系 。 【相關推薦:Redis視頻教程】
現在 , 不止 react 中實現了 hooks , 在 preact、react ssr、midway 等框架中也實現了這個特性 , 它們的實現就是不依賴 fiber 的 。
我們分別來看一下這些不同框架中的 hooks 都是怎么實現的:
react 如何實現 hooksreact 是通過 jsx 描述界面的 , 它會被 babel 或 tsc 等編譯工具編譯成 render function , 然后執行產生 vdom:
react如何實現hooks?必須依賴 Fiber 么?

文章插圖

這里的 render function 在 React17 之前是 React.createElement:
react如何實現hooks?必須依賴 Fiber 么?

文章插圖

在 React 17 之后換成了 jsx:
react如何實現hooks?必須依賴 Fiber 么?

文章插圖

這個 jsx-runtime 會自動引入 , 不用像之前那樣每個組件都要保留一個 React 的 import 才行 。
render function 執行產生 vdom:
react如何實現hooks?必須依賴 Fiber 么?

文章插圖

vdom 的結構是這樣的:
react如何實現hooks?必須依賴 Fiber 么?

文章插圖

在 React16 之前 , 會遞歸渲染這個 vdom , 增刪改真實 dom 。
react如何實現hooks?必須依賴 Fiber 么?

文章插圖

而在 React16 引入了 fiber 架構之后就多了一步:首先把 vdom 轉成 fiber , 之后再渲染 fiber 。
react如何實現hooks?必須依賴 Fiber 么?

文章插圖

vdom 轉 fiber 的過程叫做 reconcile , 最后增刪改真實 dom 的過程叫做 commit 。
為什么要做這樣的轉換呢?
因為 vdom 只有子節點 children 的引用 , 沒有父節點 parent 和其他兄弟節點 sibling 的引用 , 這導致了要一次性遞歸把所有 vdom 節點渲染到 dom 才行 , 不可打斷 。
萬一打斷了會怎么樣呢?因為沒有記錄父節點和兄弟節點 , 那只能繼續處理子節點 , 卻不能處理 vdom 的其他部分了 。
所以 React 才引入了這種 fiber 的結構 , 也就是有父節點 return、子節點 child、兄弟節點 sibling 等引用 , 可以打斷 , 因為斷了再恢復也能找到后面所有沒處理過的節點 。
fiber 節點的結構是這樣的:
react如何實現hooks?必須依賴 Fiber 么?

文章插圖

這個過程可以打斷 , 自然也就可以調度 , 也就是 schdule 的過程 。
所以 fiber 架構就分為了 schdule、reconcile(vdom 轉 fiber)、commit(更新到 dom)三個階段 。
函數組件內可以用 hooks 來存取一些值 , 這些值就是存在 fiber 節點上的 。
比如這個函數組件內用到了 6 個 hook:
react如何實現hooks?必須依賴 Fiber 么?

文章插圖

那么對應的 fiber 節點上就有個 6 個元素的 memorizedState 鏈表:
react如何實現hooks?必須依賴 Fiber 么?

文章插圖

通過 next 串聯起來:
react如何實現hooks?必須依賴 Fiber 么?

文章插圖

不同的 hook 在 memorizedState 鏈表不同的元素上存取值 , 這就是 react hooks 的原理 。
這個鏈表有創建階段和更新階段 , 所以你會發現 useXxx 的最終實現都分為了 mountXxx 和 updateXxx:
react如何實現hooks?必須依賴 Fiber 么?

文章插圖

這里的 mount 階段就是創建 hook 節點并組裝成鏈表的:
react如何實現hooks?必須依賴 Fiber 么?

文章插圖

會把創建好的 hook 鏈表掛到 fiber 節點的 memorizedState 屬性上 。
那更新的時候自然也就能從 fiber 節點上取出這個 hook 鏈表:
react如何實現hooks?必須依賴 Fiber 么?

文章插圖

這樣在多次渲染中 , useXxx 的 api 都能在 fiber 節點上找到對應的 memorizedState 。
這就是 react hooks 的原理 , 可以看到它是把 hook 存在 fiber 節點上的 。
那 preact 有什么不同呢?
preact 如何實現 hookspreact 是兼容 react 代碼的更輕量級的框架 , 它支持 class 組件和 function 組件 , 也支持了 hooks 等 react 特性 。 不過它沒有實現 fiber 架構 。

推薦閱讀