輸出:redux
{
dispatch,
subscribe,
getState,
replaceReducer,
[$$observable]: observable
}
複製代碼
這些函數會調用到閉包裏面的一些變量,如currentState, currentReducer, currentListeners。api
做用:將action和state傳入reducer並修改對應的state,並執行listeners數組裏面的全部listener 核心就是這句數組
currentState = currentReducer(currentState, action)
複製代碼
做用:將一堆reducer存在閉包裏面,最終返回一個總的reducer
輸入:一個對象,對象中每一個屬性對應一個reducerbash
{
task: (state, action) => {
switch (action.type) {
case 'CHANGE_FILTER_STATUS':
state.filterStatus = action.data
return state
default:
return state;
}
}
}
複製代碼
核心代碼:閉包
// 將reducer存到閉包中
const finalReducers = {}
for (let i = 0; i < reducerKeys.length; i++) {
const key = reducerKeys[i]
if (process.env.NODE_ENV !== 'production') {
if (typeof reducers[key] === 'undefined') {
warning(`No reducer provided for key "${key}"`)
}
}
if (typeof reducers[key] === 'function') {
finalReducers[key] = reducers[key]
}
}
// 輸出:一個總的recuder函數,做用爲遍歷全部的reducer,返回一個state
return function combination(state = {}, action) {
let hasChanged = false
const nextState = {}
for (let i = 0; i < finalReducerKeys.length; i++) {
const key = finalReducerKeys[i]
const reducer = finalReducers[key]
const previousStateForKey = state[key]
const nextStateForKey = reducer(previousStateForKey, action)
if (typeof nextStateForKey === 'undefined') {
const errorMessage = getUndefinedStateErrorMessage(key, action)
throw new Error(errorMessage)
}
nextState[key] = nextStateForKey
hasChanged = hasChanged || nextStateForKey !== previousStateForKey
}
return hasChanged ? nextState : state
}
複製代碼
核心代碼:app
const middlewareAPI = {
getState: store.getState,
dispatch: (...args) => dispatch(...args)
}
const chain = middlewares.map(middleware => middleware(middlewareAPI))
dispatch = compose(...chain)(store.dispatch)
複製代碼
其中compose其實就是使用array.reduce從右到左執行函數
compose核心代碼:ide
return funcs.reduce((a, b) => (...args) => a(b(...args)))
複製代碼
每次添加listener時都先深複製複製一份以前的listener
返回一個unsubscribe函數函數
let isSubscribed = true
ensureCanMutateNextListeners()
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 = false
ensureCanMutateNextListeners()
const index = nextListeners.indexOf(listener)
nextListeners.splice(index, 1)
}
複製代碼
用array.slice()方法來深複製ui
function ensureCanMutateNextListeners() {
if (nextListeners === currentListeners) {
nextListeners = currentListeners.slice()
}
}
複製代碼
經過分析redux的源碼,首先咱們能夠更好的理解咱們使用redux的時候,裏面具體發生了什麼事情,其次是能夠更清楚地看到各類redux的插件是如何加入到redux裏面的,對於咱們之後使用redux或者redux的插件會有幫助。
另外一方面,從代碼的組織上來看,能夠看到了裏面有不少閉包的使用,還有各類各樣的錯誤處理,以及簡潔的語法,對於自身代碼質量的提升也有必定的影響。spa