Redux源码分析(一)
Redux源碼分析(createStore)
使用redux都快3年了,到現在也沒認真去了解一下源碼罪過啊,所以需要對它進行一些分析和學習,一方面能更好的去使用它,另一方面也學習一下該框架的設計思路,首先我們看到 redux/src/index.js 文件
export {createStore,combineReducers,bindActionCreators,applyMiddleware,compose,__DO_NOT_USE__ActionTypes } 復制代碼所以主要部分也就是上面幾個函數,我們下面一點點去分析每一個功能點
createStore
其實該文件有著大量的注釋了,大家可以先簡單的看看代碼中的注釋了解一遍。 其實createStore就是返回了一個對象,這個對象只有幾個方法而已,而我們常用的就是dispatch,subscribe,getState這三個了
* Creates a Redux store that holds the state tree.* The only way to change the data in the store is to call `dispatch()` on it. 復制代碼該函數的作用呢就是建立一個store(廢話嘛),那么什么是store呢?我的理解 就是一個倉庫,存著整個程序的狀態,且只能有一個,就是用這一個store搞定項目中的全部狀態,當然不論多大的項目,統統只有這一個,弄兩個肯定不好使,并且只有一個路子去修改里面的數據,那么就是調用dispatch()
function createStore(reducer, preloadedState, enhancer) 復制代碼可以看到函數體主要三個參數,簡單說下
- reducer:它是一個函數可以表達為:(preState,action) => newState就是說根據action和之前的狀態,返回一個新的狀態(這里的新是新構建,而不是修改過,這點切記)
- preloadedState:字面理解即可,預先加載的狀態,即初始狀態
- enhancer:這個需要拿出篇幅來說了,增強劑,增強createStore
也容易理解,在只有兩個參數的情況,并且第二個為funcion的時候,那么第二個參數就是enhancer了,交互一下參數位置
if (typeof enhancer !== 'undefined') {if (typeof enhancer !== 'function') {throw new Error('Expected the enhancer to be a function.')}return enhancer(createStore)(reducer, preloadedState)} 復制代碼對enchancer類型判斷,可以看到enhancer就是將store傳入,在內部處理之后再將store返回來,繼續傳入reducer和初始狀態進行構建
let currentReducer = reducerlet currentState = preloadedStatelet currentListeners = []let nextListeners = currentListenerslet isDispatching = falsefunction ensureCanMutateNextListeners() {if (nextListeners === currentListeners) {nextListeners = currentListeners.slice()}} 復制代碼建立一些變量保存reducer,state,以及訂閱器保存在nextListeners中,ensureCanMutateNextListeners相當于每次對當前的訂閱器進行備份,因為每次訂閱一個listener的時候都是對nextListeners數組進行添加
function subscribe(listener) {if (typeof listener !== 'function') {throw new Error('Expected the listener to be a function.')}if (isDispatching) {throw new Error('You may not call store.subscribe() while the reducer is executing. ' +'If you would like to be notified after the store has been updated, subscribe from a ' +'component and invoke store.getState() in the callback to access the latest state. ' +'See https://redux.js.org/api-reference/store#subscribe(listener) for more details.')}let isSubscribed = trueensureCanMutateNextListeners()nextListeners.push(listener)return function unsubscribe() {if (!isSubscribed) {return}if (isDispatching) {throw new Error('You may not unsubscribe from a store listener while the reducer is executing. ' +'See https://redux.js.org/api-reference/store#subscribe(listener) for more details.')}isSubscribed = falseensureCanMutateNextListeners()const index = nextListeners.indexOf(listener)nextListeners.splice(index, 1)}} 復制代碼訂閱器,注冊監聽函數,每一個listener都是一個func,并且返回了一個取消注冊監聽的函數unScribe,用于刪除listener,其實就是將一個個的函數添加到數組中,之后每次在store發生變化的時候(其實也就是調用dispatch的時候)就會觸發它~
function dispatch(action) {if (!isPlainObject(action)) {throw new Error('Actions must be plain objects. ' +'Use custom middleware for async actions.')}if (typeof action.type === 'undefined') {throw new Error('Actions may not have an undefined "type" property. ' +'Have you misspelled a constant?')}if (isDispatching) {throw new Error('Reducers may not dispatch actions.')}try {isDispatching = truecurrentState = 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} 復制代碼上面呢就是這里比較重要的dispatch函數了,其實非常簡單,主要就是它:
currentState = currentReducer(currentState, action) 復制代碼將當前的全部狀態和action傳入reducer,得到新的state,這樣就完成了state的狀態更新了,之后再去遍歷全部的listeners,從而在各個listeners的內部去更新view,完成整個流程(返回值其實還是這個action對象),其實以上內容和三個函數應該是redux的核心內容了,下面用一種簡單的總結來表達一下store(借鑒的阮一峰的)
const createStore = (reducer) => {let state;let listeners = [];const getState = () => state;const dispatch = (action) => {state = reducer(state, action);listeners.forEach(listener => listener());};const subscribe = (listener) => {listeners.push(listener);return () => {listeners = listeners.filter(l => l !== listener);}};dispatch({});return { getState, dispatch, subscribe }; }; 復制代碼而該文件還有兩個函數分別是
function replaceReducer(nextReducer) function observable() 復制代碼第一個很明顯替換整個reducer用,在一些熱加載場景應該會用到 而第二個暫時還不太理解作者意圖,用觀察者替換訂閱發布嗎?暫時先不去想 以上就是整個createStore的源碼分析~
更多內容與討論可以參考我的github.com/jinjiaxing/…
轉載于:https://juejin.im/post/5cb946e4f265da038c020f2f
與50位技術專家面對面20年技術見證,附贈技術全景圖總結
以上是生活随笔為你收集整理的Redux源码分析(一)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Manjaro Linux执行某些命令缺
- 下一篇: sass和less的优缺点