这篇文章主要其实是我之前发布的《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>
结束
本人学识尚浅,文章有那么不正确的地方请大家踊跃提出。