createStore創(chuàng)建一個(gè) Redux store 來(lái)以存放應(yīng)用中所有的 state,應(yīng)用中應(yīng)有且僅有一個(gè) store。其中暴露 dispatch, subscribe, getState, replaceReducer 方法。

createStore概念圖
源碼及分析
/**
* 初始化時(shí),默認(rèn)傳遞的 action,默認(rèn)也應(yīng)該返回初始化的 state
*/
export var ActionTypes = {
INIT: '@@redux/INIT'
}
/**
* 創(chuàng)建 store, 參數(shù)根 reducer, state 以及中間件
*/
export default function createStore(reducer, preloadedState, enhancer) {
//判斷接受的參數(shù)個(gè)數(shù),來(lái)指定 reducer 、 preloadedState 和 enhancer
if (typeof preloadedState === 'function' && typeof enhancer === 'undefined') {
enhancer = preloadedState
preloadedState = undefined
}
// 如果 enhancer 存在并且適合合法的函數(shù),那么調(diào)用 enhancer,并且終止當(dāng)前函數(shù)執(zhí)行
if (typeof enhancer !== 'undefined') {
if (typeof enhancer !== 'function') {
throw new Error('Expected the enhancer to be a function.')
}
return enhancer(createStore)(reducer, preloadedState)
}
if (typeof reducer !== 'function') {
throw new Error('Expected the reducer to be a function.')
}
// 儲(chǔ)存當(dāng)前的 currentReducer
var currentReducer = reducer
// 儲(chǔ)存當(dāng)前的狀態(tài)
var currentState = preloadedState
// 儲(chǔ)存當(dāng)前的監(jiān)聽(tīng)函數(shù)列表
var currentListeners = []
// 儲(chǔ)存下一個(gè)監(jiān)聽(tīng)函數(shù)列表
var nextListeners = currentListeners
var isDispatching = false
// 這個(gè)函數(shù)可以根據(jù)當(dāng)前監(jiān)聽(tīng)函數(shù)的列表生成新的下一個(gè)監(jiān)聽(tīng)函數(shù)列表引用
function ensureCanMutateNextListeners() {
if (nextListeners === currentListeners) {
nextListeners = currentListeners.slice()
}
}
//這個(gè)函數(shù)可以獲取當(dāng)前的狀態(tài),createStore 中的 currentState 儲(chǔ)存當(dāng)前的狀態(tài)樹(shù),這是一個(gè)閉包
function getState() {
return currentState
}
// 訂閱事件,返回移除訂閱函數(shù),巧妙的利用了閉包
function subscribe(listener) {
// 判斷傳入的參數(shù)是否為函數(shù)
if (typeof listener !== 'function') {
throw new Error('Expected listener to be a function.')
}
var isSubscribed = true
ensureCanMutateNextListeners()
nextListeners.push(listener)
return function unsubscribe() {
if (!isSubscribed) {
return
}
isSubscribed = false
ensureCanMutateNextListeners()
var index = nextListeners.indexOf(listener)
nextListeners.splice(index, 1)
}
}
// 執(zhí)行 reducer,并觸發(fā)訂閱事件
function dispatch(action) {
// https://lodash.com/docs#isPlainObject
if (!isPlainObject(action)) {
throw new Error(
'Actions must be plain objects. ' +
'Use custom middleware for async actions.'
)
}
// 判斷 action 是否有 type{必須} 屬性
if (typeof action.type === 'undefined') {
throw new Error(
'Actions may not have an undefined "type" property. ' +
'Have you misspelled a constant?'
)
}
// 如果正在 dispatch 則拋出錯(cuò)誤
if (isDispatching) {
throw new Error('Reducers may not dispatch actions.')
}
// 對(duì)拋出 error 的兼容,但是無(wú)論如何都會(huì)繼續(xù)執(zhí)行 isDispatching = false 的操作
try {
isDispatching = true
// 產(chǎn)生新的 state
currentState = currentReducer(currentState, action)
} finally {
isDispatching = false
}
// 觸發(fā)訂閱的事件
var listeners = currentListeners = nextListeners
for (var i = 0; i < listeners.length; i++) {
listeners[i]()
}
return action
}
/**
* 動(dòng)態(tài)替換 reducer
*/
function replaceReducer(nextReducer) {
if (typeof nextReducer !== 'function') {
throw new Error('Expected the nextReducer to be a function.')
}
currentReducer = nextReducer
dispatch({ type: ActionTypes.INIT })
}
dispatch({ type: ActionTypes.INIT })
return {
dispatch,
subscribe,
getState,
replaceReducer
}
}
首先定義了一個(gè) ActionTypes 對(duì)象,它是一個(gè) action,是一個(gè) Redux 的私有 action,不允許外界觸發(fā),用來(lái)初始化 Store 的狀態(tài)樹(shù)和改變 reducers 后初始化 Store 的狀態(tài)樹(shù)。
參數(shù)
它可以接受三個(gè)參數(shù),reducer、preloadedState、enhancer:
- reducer:是一個(gè)函數(shù),返回下一個(gè)狀態(tài),接受兩個(gè)參數(shù):當(dāng)前狀態(tài) 和 觸發(fā)的 action;
- preloadedState:初始狀態(tài)對(duì)象,可以很隨意指定,比如服務(wù)端渲染的初始狀態(tài),但是如果使用 combineReducers 來(lái)生成 reducer,那必須保持狀態(tài)對(duì)象的 key 和 combineReducers 中的 key 相對(duì)應(yīng);
- enhancer:store 的增強(qiáng)器函數(shù),可以指定為 第三方的中間件,時(shí)間旅行,持久化 等等,但是這個(gè)函數(shù)只能用 Redux 提供的 applyMiddleware 函數(shù)來(lái)生成;
返回
調(diào)用完函數(shù)它返回的接口是 dispatch、subscribe、getStatere、placeReducer,這也是我們開(kāi)發(fā)中主要使用的幾個(gè)接口。