通常而言,我查看一個庫的源代碼,首先回查看對應方法的參數,其次是對應的return ,而後再看代碼的具體實現。git
經過查看源碼,發現createStore 方法返回了一個對象, 該對象共暴露出了五個方法,四個經常使用的方法:github
return {
dispatch,
subscribe,
getState,
replaceReducer,
[$$observable]: observable
}
複製代碼複製代碼
查看源碼的開始部分,咱們發現createStore能夠傳入兩個三個參數:redux
export default function createStore(reducer, preloadedState, enhancer)
複製代碼複製代碼
其中第一個參數reducer 是必需要傳遞的並且必須是一個函數,否則Redux回報一場數組
if (typeof reducer !== 'function') {
throw new Error('Expected the reducer to be a function.')
}
複製代碼複製代碼
若是傳遞了第二個參數preloadedState,並且第二個參數不是一個function , 則將preloadedState 保存在內部變量currentState中, 也就是咱們給State 的默認狀態bash
若是preloadedState 是一個function , 則將preloadedState 賦值給enhancerasync
if (typeof preloadedState === 'function' && typeof enhancer === 'undefined') {
enhancer = preloadedState
preloadedState = undefined
}
if (typeof enhancer !== 'undefined') {
if (typeof enhancer !== 'function') {
throw new Error('Expected the enhancer to be a function.')
}
// 運行enhancer, 通常enhancer 就是一組中間件
return enhancer(createStore)(reducer, preloadedState)
}
if (typeof reducer !== 'function') {
throw new Error('Expected the reducer to be a function.')
}
複製代碼複製代碼
該方法中保存了三個重要的變量:函數
let currentReducer = reducer
let currentState = preloadedState
let currentListeners = []
複製代碼複製代碼
咱們已經知道了Redux能控制的如上三個主要內部變量了, 接下拉咱們會 根據createStore 暴露出來的五個方法,來學習怎麼去操做這三個變量學習
return {
dispatch,
subscribe,
getState,
replaceReducer,
[$$observable]: observable
}
複製代碼複製代碼
function dispatch(action) {
try {
isDispatching = true
// 調用Reduce 對action 進行處理,每次傳入原始的state.返回更新後的states
currentState = 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
}
複製代碼複製代碼
首先須要傳遞一個action 參數來告訴須要作的操做對象,action 只能是一個Object, 並且必須包含type 字段ui
if (!isPlainObject(action)) {
throw new Error(
'Actions must be plain objects. ' +
'Use custom middleware for async actions.'
)
}
if (typeof action.type === 'undefined') { // 必須包含**Type**
throw new Error(
'Actions may not have an undefined "type" property. ' +
'Have you misspelled a constant?'
)
}
複製代碼複製代碼
咱們會調用內部變量currentReducer 去處理髮起的對應的actionspa
currentState = currentReducer(currentState, action)
複製代碼複製代碼
咱們會發現currentReducer 實際上是一個function, 並且須要兩個參數: currentState , action.
currentReducer 返回的值賦值給currentState, 由createStore 傳入參數的分析得知,preloadedState 只能是要給Object, 因此currentReducer function 返回的是要給Object.
從這一行代碼咱們能夠總結獲得:
reducer 其實就是一個函數,根據action 對 currentState 進行處理,而且返回新的currentState 的函數
const listeners = (currentListeners = nextListeners)
for (let i = 0; i < listeners.length; i++) {
const listener = listeners[i]
listener()
}
複製代碼複製代碼
由上面一段代碼咱們能夠得知,在更新state , 須要去遍歷執行全部的監聽者(listener),讓監聽者得知state變動的信息
subscribe顧名思義就是消息訂閱的意思
function subscribe(listener) {
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)
}
}
複製代碼複製代碼
很簡單的一段代碼, 傳入的參數listener 就是一個訂閱者方法,
nextListeners.push(listener)
複製代碼複製代碼
將listener 保存在內部變量數組中。返回一個unsubscribe方法, 用來取消訂閱
nextListeners.splice(index, 1) // 只要從數組中刪除listener 就是取消訂閱了
複製代碼複製代碼
function getState() {
return currentState
}
複製代碼複製代碼
很是簡單,就是返回內部變量currentState
function replaceReducer(nextReducer) {
currentReducer = nextReducer
dispatch({ type: ActionTypes.REPLACE })
}
複製代碼複製代碼
就是替換當前的reducer.
let store = createStore(reducer, preloadedState)
複製代碼複製代碼
reducer 是一個function, 並且必需要 傳遞兩個參數,第一個是state, 第二個是一個action
這個action 必需要有type 屬性