在redux中,我们如果想要对redux进行dispatch拓展,那么就需要使用中间件。
中间件:类似于插件,可以在不影响原本功能、并且不改动原本代码的基础上,对其功能进行增强。在Redux中,中间件主要用于增强dispatch函数。
实现Redux中间件的基本原理,是更改仓库中的dispatch函数。
Redux中间件书写:
- 中间件本身是一个函数,该函数接收一个store参数,表示创建的仓库,该仓库并非一个完整的仓库对象,仅包含getState,dispatch。该函数运行的时间,是在仓库创建之后运行。
。由于创建仓库后需要自动运行设置的中间件函数,因此,需要在创建仓库时,告诉仓库有哪些中间件
。需要调用applyMiddleware函数,将函数的返回结果作为createStore的第二或第三个参数。
- 中间件函数必须返回一个dispatch创建函数
- applyMiddleware函数,用于记录有哪些中间件,它会返回一个函数
。该函数用于记录创建仓库的方法,然后又返回一个函数
code
import { Middleware, MiddlewareAPI, Reducer, StoreCreator } from "redux"; /** * 实现dispatch中间件 */ export default function (...args: Middleware[]) { // 返回一个createStore创建函数 return function (createStore: StoreCreator) { // 返回一个函数,创建store,并且接收一个 reduce和defaultState的函数 return function (reducer: Reducer, defaultState?: any) { // 创建store const store = createStore(reducer, defaultState) // 获取dispatch创建函数 const minStore: MiddlewareAPI = { dispatch: store.dispatch, getState: store.getState } const dispatches = args.map(p => p(minStore)) // 最终需要返回的dispatch // 洋葱模型中间件,需要先执行最外层的dispatch中间件,对于数组来说,需要先执行最后一个dispatch const dispatch = compose(...dispatches); const finDispatch = dispatch(store.dispatch) return { ...store, dispatch: finDispatch } } } } /** * 组合函数,接收多个函数,然后从后往前运行,每一个运行的结果返回给前面一个函数,最终返回一个函数。 * @param funcs 传入的多个函数, * @returns */ function compose(...funcs: ((...args: any) => any)[]) { // 传入函数参数的数量 if (funcs.length === 0) { return (fcp: any) => fcp; } // 如果参数只有一个,那么直接执行改函数的返回结果 else if (funcs.length === 1) { return funcs[0]; } else { return funcs.reduce((a, b) => (...args) => a(b(args))) } }
使用方式
const store = applyMiddleware(logger1, logger2)(createStore)(reducer) function logger1(store: MiddlewareAPI) { console.log(1); return function (nextDispatch: Dispatch) { console.log(11); return function (action: Action) { console.log('logger1中间件1', store); console.log('logger1中间件1,store的旧值:', store.getState()); // 顺序执行,调用下一个中间件 nextDispatch(action) console.log('logger1中间件1,store的新值:', store.getState()) console.log(' '); } } } function logger2(store: MiddlewareAPI) { console.log(2); return function (nextDispatch: Dispatch) { console.log(22); return function (action: Action) { console.log('logger2中间件2', store) console.log('logger2中间件2,store的旧值:', store.getState()); // 顺序执行,调用下一个中间件 nextDispatch(action) console.log('logger2中间件2,store的新值:', store.getState()) } } }
结果: