在創建store時, ,除了reducer函數,初始狀態,還可以傳入 。這個enhancer在createStore的源碼中是這樣使用的 它可以接受createStore方法併進行 自定義改裝 ,然後再使用改裝後的方法創建倉庫。 而redux官方提供的enhancer就只有 。 applyMiddl ...
在創建store時,createStore(reducer, preloadedState, enhancer)
,除了reducer函數,初始狀態,還可以傳入enhancer
。這個enhancer在createStore的源碼中是這樣使用的
return enhancer(createStore)(reducer, preloadedState)
它可以接受createStore方法併進行自定義改裝,然後再使用改裝後的方法創建倉庫。
而redux官方提供的enhancer就只有applyMiddleware
。
applyMiddleware(...middlewares)
applyMiddleware的主要功能是改寫createStore中的dispatch
方法,並且可以將多個middleware組合到一起,形式鏈式的調用,前後互不影響。這樣要求middleware必須遵循一定的格式。({ getState, dispatch }) => next => action => {}
applyMiddleware的實現
export default function applyMiddleware(...middlewares) {
// 返回一個enhancer函數,接受createStore作為參數(可以對照enhancer的調用方式來看)
return createStore => (...args) => { // enhancer函數接受reducer, preloadedState來創建倉庫
const store = createStore(...args)
// 自定義dispatch函數,在構造middleware的時候,不允許調用dispatch
let dispatch = () => {
throw new Error(
`Dispatching while constructing your middleware is not allowed. ` +
`Other middleware would not be applied to this dispatch.`
)
}
const middlewareAPI = {
getState: store.getState, // store中的getState函數,用於獲取狀態
dispatch: (...args) => dispatch(...args) // 自定義的dispatch函數
}
// 傳入到getState,和dispatch到middleware中 生成 next => action => {} 格式的函數
const chain = middlewares.map(middleware => middleware(middlewareAPI))
// 自定義的dispatch更新為 多個middleware的組合函數;傳入store原本dispatch函數給組合函數(會在最後一個middle中作為next函數)
dispatch = compose(...chain)(store.dispatch)
// 返回store倉庫,此時的dispatch函數已被改寫,為多個middleware的組合函數
return {
...store,
dispatch
}
}
}
組合和鏈式調用
關鍵是要理解這裡dispatch = compose(...chain)(store.dispatch)
,dispatch被改寫為多個middleware的組合函數。
compose函數中關鍵的一句是return funcs.reduce((a, b) => (...args) => a(b(...args)))
a可以理解為next => action => {}
,而next
可以理解為b(...args)
就是下一個middleware的 ation => {}
函數。所以實現了鏈式調用。a中做了自定義的操作,會調用b,b調用c···最後一個調用store.dispatch
。
用兩個middleware做例子來梳理改寫後的dispatch(action)
的調用過程。
自定義middleware
middleware必須遵循一定的格式。({ getState, dispatch }) => next => action => {}
{getState, dispatch}參數是在applyMiddleware的源碼中const chain = middlewares.map(middleware => middleware(middlewareAPI))
這一部分被傳入的,store的getState和改寫後的dispatch。
next是下一個middleware或者store.dispatch,action是觸發的動作
/*logger*/
export default ({dispatch,getState}) => next => action => {
// 做一些自定義的事情
console.log('will dispatch ation',action);
console.log('next in loggere',next);
// 調用下一個middleware
let returnValue = next(action);
console.log('state after dispatch',getState());
return returnValue;
}
/*test*/
export default ({dispatch,getState}) => next => action => {
console.log('next in test',next)
return next(action);
}
使用applyMiddleware
store = createStore(reducer,applyMiddleware(logger,test))
觸發action時,有如下列印
logger做完自定義操作後,調用下一個middleware(test)函數,test是最後一個middleware,它的next是store.dispatch,就觸發了action。