Redux原始碼解讀--(5)createStore
下面介紹最後一個函式,CreateStore.先上一個基本的用法吧。
const store = createStore(reducers, state, enhance);這個enhance就是 applyMiddleware(...middleware),可以參見上一篇。
下面上原始碼吧。首先說一下,這麼多程式碼其實首次執行的邏輯很簡單,大部分程式碼都是定義了一個函式去等待呼叫的,真正就只是呼叫了一個預設的dispatch方法,初始化了一下下currentState.
export default function createStore(reducer, preloadedState, enhancer) {
if (typeof preloadedState === 'function' && typeof enhancer === 'undefined') { //第一步操作表明,可以不傳第二個引數,如果不傳則置為undefined,將enhancer過渡到第三個引數
enhancer = preloadedState
preloadedState = undefined
}
if (typeof enhancer !== 'undefined') {
if (typeof enhancer !== 'function') { //enhancer必須為函式
throw new Error('Expected the enhancer to be a function.')
}
return enhancer(createStore)(reducer, preloadedState) //如果傳遞enhancer,則把createStore作為引數傳遞過去,我在上一篇說過,第三個引數不傳也可以,因為這裡根本就不會接收!applymiddleware中會將createStore執行並返回。
}
if (typeof reducer !== 'function') {
throw new Error('Expected the reducer to be a function.')
}
let currentReducer = reducer
let currentState = preloadedState //當前的state
let currentListeners = [] //當前的listeners
let nextListeners = currentListeners
let isDispatching = false //是否正在分發
function ensureCanMutateNextListeners() { //具體這裡為什麼會淺拷貝一個陣列出來我也說不上來,有知道的麻煩幫忙解答一下
if (nextListeners === currentListeners) {
nextListeners = currentListeners.slice() //只是拷貝了一份
}
}
function getState() { //返回當前state
return currentState
}
function subscribe(listener) {
if (typeof listener !== 'function') { //監聽器要是函式
throw new Error('Expected listener to be a function.')
}
let isSubscribed = true
ensureCanMutateNextListeners()
nextListeners.push(listener)
return function unsubscribe() { //返回一個函式用來解除監聽
if (!isSubscribed) {
return
}
isSubscribed = false
ensureCanMutateNextListeners()
const index = nextListeners.indexOf(listener)
nextListeners.splice(index, 1) //從listeners中去除
}
}
function dispatch(action) {
if (!isPlainObject(action)) { //action必須是個物件{type:'XXX'}
throw new Error(
'Actions must be plain objects. ' +
'Use custom middleware for async actions.'
)
}
if (typeof action.type === 'undefined') { //物件必須有type屬性(唯一確定一個action,不能重複)
throw new Error(
'Actions may not have an undefined "type" property. ' +
'Have you misspelled a constant?'
)
}
if (isDispatching) { //不能同時執行兩個dispatch
throw new Error('Reducers may not dispatch actions.')
}
try {
isDispatching = true
currentState = currentReducer(currentState, action) //不論第一次傳入currentState是否有值,都會根據第一次的reducer返回預設值
//比如首次執行createStore就會傳入一個幾乎不會存在於reducer的case中的型別,這樣就可以返回第一次傳入reducer的預設值了。
} finally {
isDispatching = false //放開dispatch入口
}
const listeners = currentListeners = nextListeners
for (let i = 0; i < listeners.length; i++) {
const listener = listeners[i]
listener() //將監聽器執行一遍
}
return action
}
function replaceReducer(nextReducer) {
if (typeof nextReducer !== 'function') {
throw new Error('Expected the nextReducer to be a function.')
}
currentReducer = nextReducer //更換當前的reducer,並且執行預設dispatch返回預設值。
dispatch({ type: ActionTypes.INIT })
}
//由於一個正規的reducer都會返回一個預設值,執行這一步(ActionTypes真的很少會被定義),為了返回reducer的預設值。
dispatch({ type: ActionTypes.INIT })
return {
dispatch,
subscribe,
getState,
replaceReducer
}
}
大概原始碼就這些,通過上一篇我們可以發現這個middleware是可以compose的,也就是說可以組合,來達到強化dispatch的目的。那麼是不是可以通過compose這個applymiddleware來做些什麼呢?
提升:
我們發現在createStore中並沒有直接說applymiddleware,而是使用了enhancer這個名詞,增強器。
那麼我就認為applymiddleware其實是一個增強器,那肯定不止這一個嘍。比如:
const store = createStore(combineReducers({ routering: routerReducer }),
{},
composeEnhancers( //這個函式也是一個類庫中引用的
applyMiddleware(myTestMidware_delay, ...middleware,myTestMidware),
myEhancer
)
);
還是那個compose的套路,我傳遞的引數是createStore這個函式,他返回一個createStore函式,然後在下一個函式中把上一個傳入的createStore執行一下,這就是我們要做的。這裡增強的是createStore這個函式。const myEhancer = (createstore)=> (reducer, preloadedState) => {
const store = createstore(reducer, preloadedState); //接收返回的store,並繼續增強。
const dispatch = (action)=>{
console.log('我是一個Enhancer,action為:',action);
return store.dispatch(action);
}
return {...store,dispatch};
}
由於createStore不止執行性的操作,所以這裡的return 不可以省略,每次返回的都是自己增強過的store。通過增強器也可以達到增強dispatch的效果,所以能通過middleware實現的,都可以通過enhancer實現。
最後,誰知道那個ensureCanMutateNextListeners是幹嘛的啊,留言,thx.
相關文章
- Redux原始碼createStore解讀常用方法Redux原始碼
- 逐行閱讀redux原始碼(一) createStoreRedux原始碼
- Redux原始碼分析(2) - createStoreRedux原始碼
- Redux原始碼分析之createStoreRedux原始碼
- React-Redux 原始碼解析 一(createStore)ReactRedux原始碼
- Redux原始碼解讀Redux原始碼
- Redux原始碼完全解讀Redux原始碼
- Redux 原始碼解讀 —— 從原始碼開始學 ReduxRedux原始碼
- React-Redux 原始碼解讀(1)ReactRedux原始碼
- Redux-實現createStoreRedux
- redux真的不復雜——原始碼解讀Redux原始碼
- redux原始碼解讀(簡單易懂版)Redux原始碼
- Redux原始碼全篇淺讀Redux原始碼
- 重讀redux原始碼(一)Redux原始碼
- 封裝redux中的createStore封裝Redux
- 手把手教你擼一套Redux(Redux原始碼解讀)Redux原始碼
- redux 和 react-redux 部分原始碼閱讀ReduxReact原始碼
- redux 原始碼詳解Redux原始碼
- 我的原始碼閱讀之路:redux原始碼剖析原始碼Redux
- redux-logic原始碼閱讀Redux原始碼
- Redux 學習筆記 – 原始碼閱讀Redux筆記原始碼
- Redux 學習筆記 - 原始碼閱讀Redux筆記原始碼
- Vue 原始碼解讀(5)—— 全域性 APIVue原始碼API
- React-Redux v5 原始碼分析ReactRedux原始碼
- Redux解讀Redux
- 逐行閱讀redux原始碼(二)combineReducersRedux原始碼
- redux v3.7.2原始碼解讀與學習之 applyMiddlewareRedux原始碼APP
- redux && react-redux原始碼解析ReduxReact原始碼
- redux原始碼分析Redux原始碼
- Redux原始碼初探Redux原始碼
- Redux 原始碼分析Redux原始碼
- redux原始碼解析Redux原始碼
- redux v3.7.2原始碼詳細解讀與學習之composeRedux原始碼
- LLaMA 3 原始碼解讀-大語言模型5原始碼模型
- PostgreSQL 原始碼解讀(3)- 如何閱讀原始碼SQL原始碼
- WeakHashMap,原始碼解讀HashMap原始碼
- Handler原始碼解讀原始碼
- Laravel 原始碼解讀Laravel原始碼