這篇文章主要介紹“react怎么實現(xiàn)hooks”,在日常操作中,相信很多人在react怎么實現(xiàn)hooks問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”react怎么實現(xiàn)hooks”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!
江干網(wǎng)站制作公司哪家好,找成都創(chuàng)新互聯(lián)!從網(wǎng)頁設計、網(wǎng)站建設、微信開發(fā)、APP開發(fā)、響應式網(wǎng)站等網(wǎng)站項目制作,到程序開發(fā),運營維護。成都創(chuàng)新互聯(lián)公司2013年成立到現(xiàn)在10年的時間,我們擁有了豐富的建站經(jīng)驗和運維經(jīng)驗,來保證我們的工作的順利進行。專注于網(wǎng)站建設就選成都創(chuàng)新互聯(lián)。
React 的 hooks 是在 fiber 之后出現(xiàn)的特性,所以很多人誤以為 hooks 是必須依賴 fiber 才能實現(xiàn)的,其實并不是,它們倆沒啥必然聯(lián)系。
現(xiàn)在,不止 react 中實現(xiàn)了 hooks,在 preact、react ssr、midway 等框架中也實現(xiàn)了這個特性,它們的實現(xiàn)就是不依賴 fiber 的。
我們分別來看一下這些不同框架中的 hooks 都是怎么實現(xiàn)的:
react 是通過 jsx 描述界面的,它會被 babel 或 tsc 等編譯工具編譯成 render function,然后執(zhí)行產生 vdom:
這里的 render function 在 React17 之前是 React.createElement:
在 React 17 之后換成了 jsx:
這個 jsx-runtime 會自動引入,不用像之前那樣每個組件都要保留一個 React 的 import 才行。
render function 執(zhí)行產生 vdom:
vdom 的結構是這樣的:
在 React16 之前,會遞歸渲染這個 vdom,增刪改真實 dom。
而在 React16 引入了 fiber 架構之后就多了一步:首先把 vdom 轉成 fiber,之后再渲染 fiber。
vdom 轉 fiber 的過程叫做 reconcile,最后增刪改真實 dom 的過程叫做 commit。
為什么要做這樣的轉換呢?
因為 vdom 只有子節(jié)點 children 的引用,沒有父節(jié)點 parent 和其他兄弟節(jié)點 sibling 的引用,這導致了要一次性遞歸把所有 vdom 節(jié)點渲染到 dom 才行,不可打斷。
萬一打斷了會怎么樣呢?因為沒有記錄父節(jié)點和兄弟節(jié)點,那只能繼續(xù)處理子節(jié)點,卻不能處理 vdom 的其他部分了。
所以 React 才引入了這種 fiber 的結構,也就是有父節(jié)點 return、子節(jié)點 child、兄弟節(jié)點 sibling 等引用,可以打斷,因為斷了再恢復也能找到后面所有沒處理過的節(jié)點。
fiber 節(jié)點的結構是這樣的:
這個過程可以打斷,自然也就可以調度,也就是 schdule 的過程。
所以 fiber 架構就分為了 schdule、reconcile(vdom 轉 fiber)、commit(更新到 dom)三個階段。
函數(shù)組件內可以用 hooks 來存取一些值,這些值就是存在 fiber 節(jié)點上的。
比如這個函數(shù)組件內用到了 6 個 hook:
那么對應的 fiber 節(jié)點上就有個 6 個元素的 memorizedState 鏈表:
通過 next 串聯(lián)起來:
不同的 hook 在 memorizedState 鏈表不同的元素上存取值,這就是 react hooks 的原理。
這個鏈表有創(chuàng)建階段和更新階段,所以你會發(fā)現(xiàn) useXxx 的最終實現(xiàn)都分為了 mountXxx 和 updateXxx:
這里的 mount 階段就是創(chuàng)建 hook 節(jié)點并組裝成鏈表的:
會把創(chuàng)建好的 hook 鏈表掛到 fiber 節(jié)點的 memorizedState 屬性上。
那更新的時候自然也就能從 fiber 節(jié)點上取出這個 hook 鏈表:
這樣在多次渲染中,useXxx 的 api 都能在 fiber 節(jié)點上找到對應的 memorizedState。
這就是 react hooks 的原理,可以看到它是把 hook 存在 fiber 節(jié)點上的。
那 preact 有什么不同呢?
preact 是兼容 react 代碼的更輕量級的框架,它支持 class 組件和 function 組件,也支持了 hooks 等 react 特性。不過它沒有實現(xiàn) fiber 架構。
因為它主要考慮的是體積的極致(只有 3kb),而不是性能的極致。
剛才我們了解了 react 是把 hook 鏈表存放在 fiber 節(jié)點上的,那 preact 沒有 fiber 節(jié)點,會把 hook 鏈表存在哪呢?
其實也很容易想到,fiber 只是對 vdom 做了下改造用于提升性能的,和 vdom 沒啥本質的區(qū)別,那就把 hook 存在 vdom 上不就行了?
確實,preact 就是把 hook 鏈表放在了 vdom 上。
比如這個有 4 個 hooks 的函數(shù)組件:
它的實現(xiàn)就是在 vdom 上存取對應的 hook:
它沒有像 react 那樣把 hook 分為 mount 和 update 兩個階段,而是合并到一起處理了。
如圖,它把 hooks 存在了 component.__hooks 的數(shù)組上,通過下標訪問。
這個 component 就是 vdom 上的一個屬性:
也就是把 hooks 的值存在了 vnode._component._hooks 的數(shù)組上。
對比下 react 和 preact 實現(xiàn) hooks 的差異:
react 中是把 hook 鏈表存放在 fiberNode.memorizedState 屬性上,preact 中是把 hook 鏈表存放在 vnode._component._hooks 屬性上
react 中的 hook 鏈表通過 next 串聯(lián),preact 中的 hook 鏈表就是個數(shù)組,通過下標訪問
react 把 hook 鏈表的創(chuàng)建和更新分離開,也就是 useXxx 會分為 mountXxx 和 updateXxx 來實現(xiàn),而 preact 中合并在一起處理的
所以說,hooks 的實現(xiàn)并不依賴 fiber,它只不過是找個地方存放組件對應的 hook 的數(shù)據(jù),渲染時能取到就行,存放在哪里是無所謂的。
因為 vdom、fiber 和組件渲染強相關,所以存放在了這些結構上。
像 react ssr 實現(xiàn) hooks,就既沒有存在 fiber 上,也沒有存在 vdom 上:
其實 react-dom 包除了可以做 csr 外,也可以做 ssr:
csr 時使用 react-dom 的 render 方法:
ssr 的時候使用 react-dom/server 的 renderToString 方法或 renderToStream 方法:
大家覺得 ssr 的時候會做 vdom 到 fiber 的轉換么?
肯定不會呀,fiber 是為了提高在瀏覽器中運行時的渲染性能,把計算變成可打斷的,在空閑時做計算,才引入的一種結構。
服務端渲染自然就不需要 fiber。
不需要 fiber 的話,它把 hook 鏈表存放在哪里呢?vdom 么?
確實可以放在 vdom,但是其實并沒有。
比如 useRef 這個 hooks:
它是從 firstWorkInProgressHook 開始的用 next 串聯(lián)的一個鏈表。
而 firstWorkInProgressHook 最開始用 createHook 創(chuàng)建的第一個 hook 節(jié)點:
并沒有掛載到 vdom 上。
為什么呢?
因為 ssr 只需要渲染一次呀,又不需要更新,自然沒必要掛到 vdom 上。
只要每次處理完每個組件的 hooks 就清空一下這個 hook 鏈表就行:
所以,react ssr 時,hooks 是存在全局變量上的。
對比下 react csr 和 ssr 時的 hooks 實現(xiàn)原理的區(qū)別:
csr 時會從 vdom 創(chuàng)建 fiber,用于把渲染變成可打斷的,通過空閑調度來提高性能,而 ssr 時不會,是 vdom 直接渲染的
csr 時把 hooks 保存到了 fiber 節(jié)點上,ssr 時是直接放在了全局變量上,每個組件處理完就清空。因為不會用第二次了
csr 時會把 hook 的創(chuàng)建和更新分為 mount 和 update 兩個階段,而 ssr 因為只會處理一次,只有創(chuàng)建階段
hooks 的實現(xiàn)原理其實不復雜,就是在某個上下文中存放一個鏈表,然后 hooks api 從鏈表不同的元素上訪問對應的數(shù)據(jù)來完成各自的邏輯。這個上下文可以是 vdom、fiber 甚至是全局變量。
不過 hooks 這個思想還是挺火的,淘寶出的服務端框架 midway 就在引入了 hooks 的思想:
midway 是一個 Node.js 框架:
服務端框架自然就沒有 vdom、fiber 這種結構,不過 hooks 的思想并不依賴這些,實現(xiàn) hooks 的 api 只需要在某個上下文放一個鏈表就行。
midway 就實現(xiàn)了類似 react hooks 的 api:
具體它這個 hook 鏈表存在哪我還沒看,不過我們已經(jīng)掌握 hooks 的實現(xiàn)原理了,只要有個上下文存放 hook 鏈表就行,在哪都可以。
到此,關于“react怎么實現(xiàn)hooks”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續(xù)學習更多相關知識,請繼續(xù)關注創(chuàng)新互聯(lián)網(wǎng)站,小編會繼續(xù)努力為大家?guī)砀鄬嵱玫奈恼拢?/p>
文章名稱:react怎么實現(xiàn)hooks
瀏覽地址:http://weahome.cn/article/pgejdh.html