国产精品电影_久久视频免费_欧美日韩国产激情_成年人视频免费在线播放_日本久久亚洲电影_久久都是精品_66av99_九色精品美女在线_蜜臀a∨国产成人精品_冲田杏梨av在线_欧美精品在线一区二区三区_麻豆mv在线看

React 架構的演變 - Hooks 的實現

開發 架構
React Hooks 可以說完全顛覆了之前 Class Component 的寫法,進一步增強了狀態復用的能力,讓 Function Component 也具有了內部狀態,對于我個人來說,更加喜歡 Hooks 的寫法。

[[348911]]

React Hooks 可以說完全顛覆了之前 Class Component 的寫法,進一步增強了狀態復用的能力,讓 Function Component 也具有了內部狀態,對于我個人來說,更加喜歡 Hooks 的寫法。當然如果你是一個使用 Class Component 的老手,初期上手時會覺得很苦惱,畢竟之前沉淀的很多 HOC、Render Props 組件基本沒法用。而且之前的 Function Component 是無副作用的無狀態組件,現在又能通過 Hooks 引入狀態,看起來真的很讓人疑惑。Function Component 的另一個優勢就是可以完全告別 this ,在 Class Component 里面 this 真的是一個讓人討厭的東西?? 。

Hook 如何與組件關聯

在之前的文章中多次提到,Fiber 架構下的 updateQueue、effectList 都是鏈表的數據結構,然后掛載的 Fiber 節點上。而一個函數組件內所有的 Hooks 也是通過鏈表的形式存儲的,最后掛載到 fiber.memoizedState 上。

  1. function App() { 
  2.   const [num, updateNum] = useState(0) 
  3.  
  4.   return <div 
  5.     onClick={() => updateNum(num => num + 1)} 
  6.   >{ num }</div> 
  7.  
  8. export default App 

我們先簡單看下,調用 useState 時,構造鏈表的過程:

  1. var workInProgressHook = null 
  2. var HooksDispatcherOnMount = { 
  3.   useState: function (initialState) { 
  4.     return mountState(initialState) 
  5.   } 
  6.  
  7. function function mountState(initialState) { 
  8.   // 新的 Hook 節點 
  9.   var hook = mountWorkInProgressHook() 
  10.   // 緩存初始值 
  11.   hook.memoizedState = initialState 
  12.   // 構造更新隊列,類似于 fiber.updateQueue 
  13.   var queue = hook.queue = { 
  14.     pending: null
  15.     dispatch: null
  16.     lastRenderedState: initialState 
  17.   } 
  18.   // 用于派發更新 
  19.   var dispatch = queue.dispatch = dispatchAction.bind( 
  20.     null, workInProgress, queue 
  21.   ) 
  22.   // [num, updateNum] = useState(0) 
  23.   return [hook.memoizedState, dispatch] 
  24.  
  25. function mountWorkInProgressHook() { 
  26.   var hook = { 
  27.     memoizedState: null
  28.     baseState: null
  29.     baseQueue: null
  30.     queue: null
  31.     nextnull 
  32.   } 
  33.  
  34.   if (workInProgressHook === null) { 
  35.     // 構造鏈表頭節點 
  36.     workInProgress.memoizedState = workInProgressHook = hook 
  37.   } else { 
  38.     // 如果鏈表已經存在,在掛載到 next 
  39.     workInProgressHook = workInProgressHook.next = hook 
  40.   } 
  41.  
  42.   return workInProgressHook 

如果此時有兩個 Hook,第二個 Hook 就會掛載到第一個 Hook 的 next 屬性上。

  1. function App() { 
  2.   const [num, updateNum] = useState(0) 
  3.   const [str, updateStr] = useState('value: '
  4.  
  5.   return <div 
  6.     onClick={() => updateNum(num => num + 1)} 
  7.   >{ str } { num }</div> 
  8.  
  9. export default App 

Hook

Hook 的更新隊列

Hook 通過 .next 彼此相連,而每個 Hook 對象下,還有個 queue 字段,該字段和 Fiber 節點上的 updateQueue 一樣,是一個更新隊列在,上篇文章 《React 架構的演變-更新機制》中有講到,React Fiber 架構中,更新隊列通過鏈表結構進行存儲。

  1. class App extends React.Component { 
  2.   state = { val: 0 } 
  3.   click () { 
  4.     for (let i = 0; i < 3; i++) { 
  5.       this.setState({ val: this.state.val + 1 }) 
  6.     } 
  7.   } 
  8.   render() { 
  9.     return <div onClick={() => { 
  10.       this.click() 
  11.     }}>val: { this.state.val }</div> 
  12.   } 

點擊 div 之后,產生的 3 次 setState 通過鏈表的形式掛載到 fiber.updateQueue 上,待到 MessageChannel 收到通知后,真正執行更新操作時,取出更新隊列,將計算結果更新到 fiber.memoizedState。

setState

而 hook.queue 的邏輯和 fiber.updateQueue 的邏輯也是完全一致的。

  1. function App() { 
  2.   const [num, updateNum] = useState(0) 
  3.  
  4.   return <div 
  5.     onClick={() => { 
  6.       // 連續更新 3 次 
  7.       updateNum(num => num + 1) 
  8.       updateNum(num => num + 1) 
  9.       updateNum(num => num + 1) 
  10.     }} 
  11.   > 
  12.     { num } 
  13.   </div> 
  14.  
  15. export default App; 
  16. var dispatch = queue.dispatch = dispatchAction.bind( 
  17.   null, workInProgress, queue 
  18. // [num, updateNum] = useState(0) 
  19. return [hook.memoizedState, dispatch] 

調用 useState 的時候,返回的數組第二個參數為 dispatch,而 dispatch 由 dispatchAction bind 后得到。

  1. function dispatchAction(fiber, queue, action) { 
  2.   var update = { 
  3.     nextnull
  4.     actionaction
  5.     // 省略調度相關的參數... 
  6.   }; 
  7.  
  8.   var pending = queue.pending 
  9.   if (pending === null) { 
  10.     update.next = update 
  11.   } else { 
  12.     update.next = pending.next 
  13.     pending.next = update 
  14.   } 
  15.   queue.pending = update 
  16.  
  17.   // 執行更新 
  18.   scheduleUpdateOnFiber() 

可以看到這里構造鏈表的方式與 fiber.updateQueue 如出一轍。之前我們通過 updateNum 對 num 連續更新了 3 次,最后形成的更新隊列如下:

更新隊列

函數組件的更新

前面的文章分享過,Fiber 架構下的更新流程分為遞(beginWork)、歸(completeWork)兩個步驟,在 beginWork 中,會依據組件類型進行 render 操作構造子組件。

  1. function beginWork(current, workInProgress) { 
  2.   switch (workInProgress.tag) { 
  3.     // 其他類型組件代碼省略... 
  4.     case FunctionComponent: { 
  5.       // 這里的 type 就是函數組件的函數 
  6.       // 例如,前面的 App 組件,type 就是 function App() {} 
  7.       var Component = workInProgress.type 
  8.       var resolvedProps = workInProgress.pendingProps 
  9.       // 組件更新 
  10.       return updateFunctionComponent( 
  11.         current, workInProgress, Component, resolvedProps 
  12.       ) 
  13.     } 
  14.   } 
  15.  
  16. function updateFunctionComponent( 
  17.  current, workInProgress, Component, nextProps 
  18. ) { 
  19.   // 構造子組件 
  20.   var nextChildren = renderWithHooks( 
  21.     current, workInProgress, Component, nextProps 
  22.   ) 
  23.   reconcileChildren(current, workInProgress, nextChildren) 
  24.   return workInProgress.child 

看名字就能看出來,renderWithHooks 方法就是構造帶 Hooks 的子組件。

  1. function renderWithHooks( 
  2.  current, workInProgress, Component, props 
  3. ) { 
  4.   if (current !== null && current.memoizedState !== null) { 
  5.     ReactCurrentDispatcher.current = HooksDispatcherOnUpdate 
  6.   } else { 
  7.     ReactCurrentDispatcher.current = HooksDispatcherOnMount 
  8.   } 
  9.   var children = Component(props) 
  10.   return children 

從上面的代碼可以看出,函數組件更新或者首次渲染時,本質就是將函數取出執行了一遍。不同的地方在于給 ReactCurrentDispatcher 進行了不同的賦值,而 ReactCurrentDispatcher 的值最終會影響 useState 調用不同的方法。

根據之前文章講過的雙緩存機制,current 存在的時候表示是更新操作,不存在的時候表示首次渲染。

  1. function useState(initialState) { 
  2.   // 首次渲染時指向 HooksDispatcherOnMount 
  3.   // 更新操作時指向 HooksDispatcherOnUpdate 
  4.   var dispatcher = ReactCurrentDispatcher.current 
  5.   return dispatcher.useState(initialState) 

HooksDispatcherOnMount.useState 的代碼前面已經介紹過,這里不再著重介紹。

  1. // HooksDispatcherOnMount 的代碼前面已經介紹過 
  2. var HooksDispatcherOnMount = { 
  3.   useState: function (initialState) { 
  4.     return mountState(initialState) 
  5.   } 

我們重點看看 HooksDispatcherOnMount.useState 的邏輯。

  1. var HooksDispatcherOnUpdateInDEV = { 
  2.   useState: function (initialState) { 
  3.     return updateState() 
  4.   } 
  5.  
  6. function updateState() { 
  7.   // 取出當前 hook 
  8.   workInProgressHook = nextWorkInProgressHook 
  9.   nextWorkInProgressHook = workInProgressHook.next 
  10.  
  11.   var hook = nextWorkInProgressHook 
  12.   var queue = hook.queue 
  13.   var pendingQueue = queue.pending 
  14.  
  15.   // 處理更新 
  16.   var first = pendingQueue.next 
  17.   var state = hook.memoizedState 
  18.   var update = first 
  19.  
  20.   do { 
  21.     var action = update.action 
  22.     state = typeof action === 'function' ? action(state) : action 
  23.  
  24.     update = update.next
  25.   } while (update !== null && update !== first
  26.  
  27.  
  28.   hook.memoizedState = state 
  29.  
  30.   var dispatch = queue.dispatch 
  31.   return [hook.memoizedState, dispatch] 

如果有看之前的 setState 的代碼,這里的邏輯其實是一樣的。將更新對象的 action 取出,如果是函數就執行,如果不是函數就直接對 state 進行替換操作。

總結

React 系列的文章終于寫完了,這一篇文章應該是最簡單的一篇,如果想拋開 React 源碼,單獨看 Hooks 實現可以看這篇文章:《React Hooks 原理》。Fiber 架構為了能夠實現循環的方式更新,將所有涉及到數據的地方結構都改成了鏈表,這樣的優勢就是可以隨時中斷,為異步模式讓路,Fiber 樹就像一顆圣誕樹,上面掛滿了各種彩燈(alternate、EffectList、updateQueue、Hooks)。

本文轉載自微信公眾號「 更了不起的前端  」,可以通過以下二維碼關注。轉載本文請聯系更了不起的前端  公眾號。

 

責任編輯:武曉燕 來源: 更了不起的前端
相關推薦

2022-04-16 20:10:00

React Hookfiber框架

2020-09-30 09:15:24

React架構遞歸

2020-10-13 08:36:30

React 架構機制

2020-09-24 08:45:10

React架構源碼

2022-08-21 09:41:42

ReactVue3前端

2023-11-06 08:00:00

ReactJavaScript開發

2022-03-31 17:54:29

ReactHooks前端

2020-09-19 17:46:20

React Hooks開發函數

2024-06-04 14:17:26

2019-08-20 15:16:26

Reacthooks前端

2023-05-29 13:56:00

JSReact

2021-03-18 08:00:55

組件Hooks React

2023-05-08 07:52:29

JSXReactHooks

2021-05-11 08:48:23

React Hooks前端

2022-02-10 19:15:18

React監聽系統模式

2022-03-16 22:24:50

ReactstateHooks

2020-08-10 06:31:01

React Hooks前端開發

2021-11-05 10:36:19

性能優化實踐

2022-11-15 17:31:35

邊緣計算架構人工智能

2019-03-13 10:10:26

React組件前端
點贊
收藏

51CTO技術棧公眾號

四虎国产精品永远| 一个人看的www视频在线免费观看| 热久久免费视频| 国产精品久久久久久久7电影| 欧美黄色网络| 亚洲免费精彩视频| 国产蜜臀在线| 精品少妇一区二区| 毛片在线播放a| 欧美日本在线视频| 天天影视久久综合| 777色狠狠一区二区三区| 成人免费黄色网页| 91久久线看在观草草青青| 亚洲高清国产精品| 精品国产91久久久久久| 啦啦啦啦免费高清视频在线观看1| 亚洲精品国产a久久久久久 | 成人欧美一区二区三区白人| 蜜臀视频一区二区三区| 91视视频在线观看入口直接观看www| 玖玖精品在线视频| 国产美女精品一区二区三区| 亚洲精品无码国产| 久久精品人人爽人人爽| 国产无遮挡又黄又爽免费网站| 亚洲最新在线观看| 在线播放色视频| 色域天天综合网| 黄av在线播放| 日韩精品高清在线观看| 日韩综合久久| 欧美中文字幕精品| 伊人久久大香线蕉综合四虎小说 | 亚洲一区二区在线免费看| 97在线资源| 欧洲生活片亚洲生活在线观看| 亚洲s色大片| 欧美mv日韩mv国产网站app| 男女羞羞在线观看| 欧美插天视频在线播放| 精品国产欧美日韩| 国产精品一区二区欧美黑人喷潮水| 久久国产精品亚洲77777| 中文视频一区视频二区视频三区| 国产99久久久国产精品潘金 | 国内精品美女av在线播放| 欧美自拍偷拍| 噜噜噜噜噜久久久久久91| 国产精品88av| 成人www视频网站免费观看| 精品久久香蕉国产线看观看gif| 精品视频二区| 亚洲黄页网在线观看| 日韩欧美另类中文字幕| 亚洲一区二区三区在线视频 | 91欧美激情另类亚洲| 美女精品在线观看| www插插插无码视频网站| 一区二区三区资源| 欧美jizzhd欧美| 欧美成人全部免费| 亚洲午夜电影| 欧美成人免费高清视频| 在线亚洲人成电影网站色www| 欧美日韩视频免费观看| 欧美在线免费观看| 久久综合激情| 天天插天天操天天射| 欧美日韩亚洲高清一区二区| 欧美韩国日本| 久久青青草综合| 国产日韩欧美高清在线| 免费av在线| 97婷婷大伊香蕉精品视频| 国产农村妇女精品一区二区| 日韩精品一区二区三区久久| 欧美日韩高清在线播放| 中文字幕一区图| 日韩精品不卡| 亚洲一级二级三级| 日韩毛片免费看| 欧美亚州在线观看| 亚洲国产精品影院| 91成人小视频| 亚洲成人午夜在线| 欧美日韩国产精品一区二区三区四区| 精品国产欧美日韩一区二区三区| 亚洲最大福利视频网| 国产香蕉久久精品综合网| 2021中文字幕在线| 91九色蝌蚪嫩草| 欧美国产欧美综合| 经典三级一区二区| 欧美主播一区二区三区美女 久久精品人 | 国产精品高潮呻吟久久av黑人| 免费亚洲一区| 久久久久久77777| 日韩在线精品一区| 男人的天堂久久精品| 欧美新色视频| 国产精品吹潮在线观看| 91蝌蚪porny| 欧美第一视频| 一本一道久久a久久综合精品| 色8久久精品久久久久久蜜| 亚洲精品亚洲人成在线| 成年人观看网站| 亚洲片av在线| 美女脱光内衣内裤视频久久影院| 91欧美在线视频| 91精品国产综合久久久久久蜜臀| 日本一二三四高清不卡| www.欧美| 狠狠97人人婷婷五月| 亚洲欧洲国产伦综合| 美国欧美日韩国产在线播放| av免费在线观看网站| 国产精品一区二区av| 色噜噜久久综合| 国产精品x453.com| 中文字幕在线免费观看| 国产精品91久久久久久| 亚洲欧美国产77777| 亚洲欧洲av| 秋霞在线观看av| 国产ts人妖一区二区三区 | 一区中文字幕在线观看| 日韩欧美一区二区视频| 免费看亚洲片| 激情影院在线| eeuss中文| 在线看福利67194| eeuss影院一区二区三区| 澳门av一区二区三区| www.av片| 久久久久亚洲精品| 亚洲婷婷在线视频| 国产一区二区三区四区五区传媒| 天堂在线看视频| 97超碰人人看人人| 制服视频三区第一页精品| 日韩电影在线一区二区三区| 亚洲精品一区| 可以免费观看av毛片| 欧美一级免费视频| 欧美日韩亚洲91| 久久成人在线| 中文字幕成在线观看| 国产精品亚洲a| 国产精品日韩在线观看| 精品视频资源站| 蓝色福利精品导航| 日本午夜精品久久久久| www.av99| 粉嫩av一区二区三区免费观看| 正在播放亚洲一区| 国产精品亚洲第一| 一区中文字幕电影| 天堂在线看视频| 久久99精品久久久久久久青青日本| 亚洲成人免费在线视频| 99综合电影在线视频| 亚洲小说图片视频| 美女隐私在线观看| 国产日韩欧美精品在线观看| 91精品国产电影| 欧美视频完全免费看| 国产精品系列在线播放| 91精品导航| 国产女人在线视频| 中文字幕一区二区三区最新| 九九热精品视频| 一本色道久久加勒比精品 | 粉嫩av一区二区三区免费观看| 精品成人在线观看| 欧美激情一二三区| 激情欧美丁香| 日韩欧美精品电影| 久久久亚洲精华液精华液精华液 | 丝袜连裤袜欧美激情日韩| 成人网视频在线观看| 久久久久久久久久久福利| 亚洲影院色无极综合| 国产亚洲aⅴaaaaaa毛片| 国产精品久久久久久久裸模| 99久久久久国产精品| 天堂中文在线播放| 国产无遮挡在线视频免费观看| 欧美中日韩在线| 91影视免费在线观看| 国产成人无遮挡在线视频| 国产成人aa在线观看网站站| 国产二区视频在线观看| 免费高清一区二区三区| 91精品国产自产在线观看永久| 精品网站999www| 欧美日韩亚洲系列| 久久天天做天天爱综合色| 性欧美长视频|