参考redux仓库, redux-logger库
所有1-8系列代码仓库
- 新建个项目吧 - 引入 redux, react-redux
中间件执行流程图
演示代码仓库
就这个演示了,点击 + 1 ,现在呢, 我想打印个日志,就是每次点击按钮,都能打印出老的状态和新的状态
- 理逻辑,既然是在每次点击事件之后打印,那么,如果想拿到老的状态,就需要在派发前,想拿到新的状态,就是在派发后
先这样写:
let store = createStore(reducers);
let dispatch = store.dispatch;
store.dispatch = function(action) {
console.log(`老值: ${JSON.stringify(store.getState())}`);
dispatch(action);
console.log(`新值:${JSON.stringify(store.getState())}`);
};
export default store
这样一来已经实现了,那上边的代码,核心就是重写 了
redux的
dispatch方法
,
- 先存起来一份老的, 用于用户的派发action
- 再重写一份 dispatch 方法, 用于,在派发前和派发后做某些事
- 接着整个异步逻辑,点击延时1秒再加1, 接着
重写 dispatch
, 1秒后,再派发action
store.dispatch = function(action) {
setTimeout(() => {
dispatch(action);
}, 1000);
};
参考logger的实现第67行开始, 可以看到 连续返回了3个函数, 同时,第一个参数拿到getState, 第二个参数传入老的 dispatch, 第三个参数就是reducer,接着实现一个简化版logger中间件
function logger({ getState }) {
return function(next) {
return function(action) {
console.log(`老值: ${JSON.stringify(getState())}`);
next(action);
console.log(`新值: ${JSON.stringify(getState())}`);
};
};
}
let store = applyMiddleware(logger)(createStore)(reducers)
好了, 来接着推导 applyMiddleware
方法, 它接收的参数有 自己写的 logger 中间件, redux的 createStore
方法, 还有自己的reducer
, 它连续返回了3个函数, 代码实现就是下边这样的
// 传入自己的中间件
function applyMiddleware(middleWare) {
// 传入 redux 的 createStore 方法
return function(createStore) {
// 传入自己的reducer
return function(reducer) {
let store = createStore(reducer);
// 包裹了一圈, 最后还是返回了 store因为外部要接收store对象
// 此时,还没有处理 中间件 middleWare 参数
return store;
};
};
}
处理 传入的 middleWare
参数 (也就是中间件)
function applyMiddleware(middleWare) {
// 传入 redux 的 createStore 方法
return function(createStore) {
// 传入自己的reducer
return function(reducer) {
let store = createStore(reducer);
// 处理middleWare 参数, 看着上边的 logger 函数写
// 1. 先执行第一次传入 store 实参, 供 logger 组件解构出 getState 参数
middleWare = middleWare(store)
// 再执行第二次 传入 dispatch 供 next 使用派发action
let dispatch = middleWare(store.dispatch)
// 将这个与 store的 dispatch 进行替换掉
return {
...store,
dispatch
};
};
};
}
打印,实现了 单一中间件的处理,但实际开发中,中间件可能有多个的,下篇再接着聊