1,介绍
中间件:和插件的作用差不多,能够在不影响原本功能、不改动原本代码的基础下,增强其功能。
在 Redux 中,中间件主要为了增强 dispatch
函数。
2,核心原理
1,一个问题
一般情况下,想在触发 dispatch
时,监听并获取 action
和新旧 state
是比较困难的,
store.subscribe()
只能监听到变化。- 直接修改
dispatch
源码,参考 createStore 中dispatch
的写法。
换一个思路,不修改 dispatch
源码,而是将 store.dispatch
指向一个新函数,并在适当时机调用原本的 dispatch
:
const store = createStore(reducer);
const originDispatch = store.dispatch;
store.dispatch = (action) => {
console.log("重写的函数");
console.log("旧数据", store.getState());
originDispatch(action);
console.log("新数据", store.getState());
console.log("-----");
};
这个新函数就是中间件。
3,Redux 使用中间件
import { createStore, applyMiddleware } from "redux";
const store = createStore(reducer, applyMiddleware(logger1, logger2));
通过 applyMiddleware
来使用中间件。
createStore
的第一个参数是reducer
,第2个参数可以是初始化的state
,如果有该参数,则applyMiddleware
会作为第3个参数传入。
1,中间件的写法
中间件本质是一个函数,
- 参数,一个
store
函数,表示仓库对象,但并不完整,只有getState
和dispatch
2个属性。 - 返回值,必须返回一个用于创建
dispatch
的函数。 - 运行时间点,仓库创建后运行。
const logger = (store) => {
// 用于创建 dispatch 的函数
return (nextDispatch) => {
// 最终应用的新 dispatch
return (action) => {
console.log("中间件");
console.log("旧数据", store.getState());
nextDispatch(action);
console.log("新数据", store.getState());
console.log("-----");
};
};
};
在解释 nextDispatch
这个参数前,先了解下如果有多个中间件时,它们的执行顺序。
2,多个中间件的执行顺序
比如书写顺序如下:
const store = createStore(reducer, applyMiddleware(logger1, logger2, logger3));
初始化时,原始 dispatch
的流转顺序:
![](https://i-blog.csdnimg.cn/direct/50f083860d5847569cef10bd4160cd39.png)
所以 nextDispatch
,
- 对中间件3来说,是原始的
store.dispatch
, - 对中间件2来说,是中间件3返回的新
dispatch
, - 对中间件1来说,是中间件2返回的新
dispatch
,
最终中间件的执行顺序:
经历了初始化后,当使用 store.dispatch
分发 action
时,此时的 store.dispatch
是中间件1 最终返回 dispatch
。
这样就实现了:正序调用中间件函数,倒序传递 dispatch。
注意到中间件函数的参数是
store
,部分情况下也可直接使用原始的store.dispatch
。
现在还有2个问题,
applyMiddleware
是如何处理中间件函数,来保证执行顺序的。- 用于创建
dispatch
的函数,是什么时候执行的。
接下篇文章:实现 applyMiddleware
以上。