Redux源码简析
Redux核心概念
- 單一 store ,只能挺過getState()獲取狀態,不能直接修改
- 只能通過觸發 action 修改狀態
- 使用純函數 reducers 描述action如何改變state
整個redux的實現就是圍繞上面的這三點進行實現的,整個源碼量不大,理解了核心概念后去看源碼會發現源碼的結構邏輯非常清晰,代碼中的注釋也非常全面,本篇文章會按照如何實現核心概念的方式去閱讀源碼。(默認你已經會使用redux了)
Reducer
我們首先來看 reducer 在 redux中的使用來更加深入理解reducer的作用
currentState = currentReducer(currentState, action)這是 redux 中唯一使用到 reducer 的地方,在dispatch函數中,將舊的state和dispatch的action傳入得到新的state,這和redux對于reducer的描述是一模一樣的,所以我們在編寫 reducer 函數的時候一定要嚴格遵循redux的規范寫成純函數,這樣可以保證你的state變化可以被方便的追蹤到。
Action
我們所有的action都要通過 dispatch 所以我們直接來看dispatch的實現,比較有意思的就是redux內其實是有一把同步鎖 isDispatching ,這樣的做法避免掉了很多處理并發的邏輯,例如并發會帶來讀臟數據的風險,在看源碼之前是根本不知道redux有這樣的一個設計的。
function dispatch(action) {// 省略了一些錯誤aciton的檢測代碼 總結下來就是aciton一定是對象并且有type屬性// isDispatching 類似于同步鎖,保證每次修改state的原子性if (isDispatching) {throw new Error('Reducers may not dispatch actions.')}try {isDispatching = true//獲取新的statecurrentState = currentReducer(currentState, action)} finally {//開鎖isDispatching = false}//通知訂閱的函數const listeners = (currentListeners = nextListeners)for (let i = 0; i < listeners.length; i ) {const listener = listeners[i]listener()}return action}Store
redux最重要的部分就是createStore,他將存儲state,把reducer和action組合在一起。
// 接收 reducer 初始state applyMiddleware添加中間件后返回的函數 export default function createStore(reducer, preloadedState, enhancer) {// 解決我們不傳 preloadedState 第二個參數是 enhancer 的情況if (typeof preloadedState === 'function' && typeof enhancer === 'undefined') {enhancer = preloadedStatepreloadedState = undefined}if (typeof enhancer !== 'undefined') {if (typeof enhancer !== 'function') {throw new Error('Expected the enhancer to be a function.')}// 在 applyMiddleware 中enhancer做的事情就是添加中間件增強dispatch的能力return enhancer(createStore)(reducer, preloadedState)}if (typeof reducer !== 'function') {throw new Error('Expected the reducer to be a function.')}//store中的轉態let currentReducer = reducer//我們的state樹let currentState = preloadedStatelet currentListeners = []let nextListeners = currentListenerslet isDispatching = false...//返回 store對象以及apireturn {//觸發aciton使用dispatch,//添加state改變的回調使用subscribe,//獲取 stategetState,//替換 reducerreplaceReducer,[$$observable]: observable}總結
整個redux源碼看下來大概只需要一個小時,但是整體的收獲還是非常大的,我們可以看到redux作者是從核心概念入手,一點點將其轉化為工具的。
更多專業前端知識,請上 【猿2048】www.mk2048.com
總結
- 上一篇: 面试常见问题之实现bind函数
- 下一篇: scroll-view组件bindscr