這篇文章主要其實是我之前釋出的《Redux 原始碼分析》的補充,這一篇主要來聊一下applyMiddleware ,就是Redux的中介軟體
Redux呼叫中介軟體過程
如何引入中介軟體
如果我們想在Redux中使用中介軟體,在建立stores時這麼寫
import { createStore,applyMiddleware } from `redux`
let store = createStore(
todoApp,
// ...middleware 代表你要傳入的中介軟體
applyMiddleware(...middleware)
)
複製程式碼
引入中介軟體時createStore的處理
看下createStore部分的原始碼最開始部分,
//reducer是傳入的reducer,preloadedState是初始化時的state,enhancer就是增強器。
function createStore(reducer, preloadedState, enhancer) {
//當你只傳了兩個引數,而且第二個引數是function就當你傳入了增強器
if (typeof preloadedState === `function` && typeof enhancer === `undefined`) {
enhancer = preloadedState;
preloadedState = undefined;
}
//再判斷不是undefined和確定是function後,返回一個傳入了createStore返回的函式再傳入
if (typeof enhancer !== `undefined`) {
if (typeof enhancer !== `function`) {
throw new Error(`Expected the enhancer to be a function.`);
}
//reducer, preloadedState(這裡的preloadedState已經在上面賦值undefined了)呼叫然後return。
return enhancer(createStore)(reducer, preloadedState);
}
}
複製程式碼
Redux文件沒有說enhancer就是applyMiddleware,applyMiddleware只是Redux提供給我們的一箇中介軟體載入器而已,如果有特殊場景我們也可以做一個像applyMiddleware的中介軟體載入器,就是要按照Redux的規範來寫。
比如我們的enhancer就是Redux提供的applyMiddleware,我們接著往下說。
applyMiddleware的處理
function applyMiddleware() {
//首先applyMiddleware把所有中介軟體存到middlewares陣列
for (var _len = arguments.length, middlewares = Array(_len), _key = 0; _key < _len; _key++) {
middlewares[_key] = arguments[_key];
}
//通過createStore高階函式的處理,applyMiddleware就是個包含createStore函式的閉包。
//然後傳入reducer, preloadedState建立store。
return function (createStore) {
return function (reducer, preloadedState, enhancer) {
var store = createStore(reducer, preloadedState, enhancer);
var _dispatch = store.dispatch;
var chain = [];
//宣告 middlewareAPI 包含 getState 和 dispatch, dispatch可以呼叫store的dispatch方法
var middlewareAPI = {
getState: store.getState,
dispatch: function dispatch(action) {
return _dispatch(action);
}
};
//然後用map所有中介軟體傳入middlewareAPI呼叫,存入chain陣列。因此中介軟體寫法首先會獲取dispatch, getState兩個引數。
chain = middlewares.map(function (middleware) {
return middleware(middlewareAPI);
});
//compose是個遞迴函式的方法。
//這裡會chain中的函式傳入store.dispatch然後遞迴呼叫,就是會把上一個中介軟體的返回值傳遞給下一個中介軟體.
_dispatch = _compose2[`default`].apply(undefined, chain)(store.dispatch);
//最後合併 這就是createStore的返回值
return _extends({}, store, {
dispatch: _dispatch
});
};
};
}
複製程式碼
Redux簡單中介軟體的寫法
const midde = function({ dispatch, getState }){
return function(dispatch){
return function(action){
//中間間處理
return dispatch(action)
};
};
};
複製程式碼
Redux-thunk原始碼分析
上面瞭解中介軟體的執行機制,我想我們拿一個簡單中介軟體看看是怎麼寫的。
沒使用Redux-thunk的寫法
如果我們寫把action寫成函式的形式我們要這麼寫,而且還要傳入dispatch
action
function showNotificationWithTimeout(text) {
dispatch(showNotification(`You just logged in.`))
setTimeout(() => {
dispatch(hideNotification())
}, 5000)
}
複製程式碼
元件
<button (text)=>{ showNotificationWithTimeout(this.props.dispatch,text)) } ></button>
複製程式碼
Redux-thunk中介軟體能讓我們的中介軟體寫成action寫成函式的形式呼叫,然後通過中介軟體注入dispatch, getState可以讓我們處理。
`use strict`;
exports.__esModule = true;
function createThunkMiddleware(extraArgument) {
return function (_ref) {
var dispatch = _ref.dispatch,
getState = _ref.getState;
return function (next) {
return function (action) {
//如果action是function
//把引數dispatch, getState, extraArgument 傳入action呼叫
//如果直接引入Redux-thunk模組,extraArgument預設為undefind,extraArgument是thunk提供可以自定義傳遞引數的一個引數。
if (typeof action === `function`) {
return action(dispatch, getState, extraArgument);
}
//不是function就dispatch
return next(action);
};
};
};
}
var thunk = createThunkMiddleware();
//引用thunk.withExtraArgument就我們就可以傳入extraArgument引數
thunk.withExtraArgument = createThunkMiddleware;
exports[`default`] = thunk;
複製程式碼
現在我們就可以這麼寫
action
function showNotificationWithTimeout(text) {
return (dispatch) =>{
dispatch(showNotification(`You just logged in.`))
setTimeout(() => {
dispatch(hideNotification())
}, 5000)
}
}
複製程式碼
元件
const dispatch = { this.props }
<button (text)=>{ dispatch(showNotificationWithTimeout(text)) } ></button>
複製程式碼
結束
本人學識尚淺,文章有那麼不正確的地方請大家踴躍提出。