前言
最近看了一下Redux的官方文檔,突然感覺(jué)以前忽略了很多東西,現(xiàn)在回頭看看,正好記錄一下,并且加深印象
中間件的使用
const store = createStore(reducers,applyMiddleware(logger));
以上是應(yīng)用了redux-logger中間件的代碼,只要按照官方提供的規(guī)定格式實(shí)現(xiàn),并應(yīng)用到中間件方法,那么,在執(zhí)行一個(gè)action的時(shí)候,就會(huì)調(diào)用中間件。
在官方的示例中,有一個(gè)logger實(shí)現(xiàn)的示例
const logger = store => next => action =>{
console.log('prev state',store.getState())
console.log('dispatch',action);
let result = next(action);
console.log('next state',store.getState());
return result;
}
從這個(gè)示例可以看出,實(shí)現(xiàn)一個(gè)中間件需要做一下幾件事情:
- 三層函數(shù)包裝:第一層傳入store,第二層傳入下一個(gè)中間件next,第三層傳入此次執(zhí)行的action;
2.在最內(nèi)層的函數(shù)實(shí)現(xiàn)中,需要調(diào)用next中間件,并返回結(jié)果。
原理解析
首先來(lái)看一下createStore
- createStore(reducer, preloadedState, enhancer)
createStore有三個(gè)參數(shù)1.reducer;2.preloadedState;3.enhancer
reducer :即一些改變state的純函數(shù),這個(gè)可以在官方文檔查看具體定義;
preloadesState:是初始化的state,這個(gè)state可以是加載頁(yè)面時(shí)從服務(wù)器提供的初始化state值,這個(gè)為服務(wù)器端渲染,并與客戶端保持?jǐn)?shù)據(jù)一致提供可能;
enhancer: store增強(qiáng)功能,在redux中特指applyMiddleware()方法的返回值;
來(lái)看看createStore方法的開(kāi)頭部分
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.')
}
return enhancer(createStore)(reducer, preloadedState)
}
if (typeof reducer !== 'function') {
throw new Error('Expected the reducer to be a function.')
}
這里面第二個(gè)判斷if中有enhancer為function則調(diào)用enhander(createStore)(reducer,preloadedState);我們都知道enhancer 是applyMiddleware方法的返回值,
下面在看applyMiddleware方法
- applyMiddleware(...middlewares)
參數(shù)即為所有要使用的符合redux的中間件;
apllyMiddleware的代碼很精簡(jiǎn)
export default function applyMiddleware(...middlewares) {
return (createStore) => (reducer, preloadedState, enhancer) => {
const store = createStore(reducer, preloadedState, enhancer)
let dispatch = store.dispatch
let chain = []
const middlewareAPI = {
getState: store.getState,
dispatch: (action) => dispatch(action)
}
chain = middlewares.map(middleware => middleware(middlewareAPI))
dispatch = compose(...chain)(store.dispatch)
return {
...store,
dispatch
}
}
}
來(lái)分析一下applyMiddleware方法,
- 接收一個(gè)middleware數(shù)組作為參數(shù),返回一個(gè)方法,我們暫且叫它enhancer;
- enhancer仍然是一個(gè)方法,他接收createStore方法作為參數(shù),enhancer方法返回的還是一個(gè)方法,這個(gè)方法的參數(shù)與createStore方法的的簽名一樣,都包含三個(gè)參數(shù),分別是reducer, preloadedState, enhancer;我們叫它mergeDispatch;
- mergeDispatch這個(gè)最終的方法的作用有2點(diǎn),首先調(diào)用createStore創(chuàng)建store,然后就是不斷的替換store.dispatch,以達(dá)到應(yīng)用中間件的目的,大概流程如下:

最終就是把原始的store.dispatch應(yīng)用到所有的中間件的最核心的位置調(diào)用,其他的插件都在原始的dispatch外層包裹著。