Open zlx362211854 opened 4 years ago
redux
这里就不过多介绍了,那么什么是 redux
中间件呢?现在我们看一下没有中间件的数据传递流程:
// 相关组件订阅 store ,获取更新数据
// actions 引发数据更新的动作,数据结构为对象形式
store -> store.dispatch(actions) -> reducer -> state
那么加入中间件之后:
// actionCreators 为中间件函数,主要作用是对数据进行封装后传递
store -> store.dispatch(actionCreators) -> dispatch(action) -> reducer -> state
综上,简单来讲,中间件可以理解为在触发动作更新前,对需要更新的数据在中间件函数中做一些封装改变,使整个数据流操作更加的顺滑和语义化.
let next = store.dispatch;
store.dispatch = function dispatchAndLog(action) {
console.log('dispatching', action);
next(action);
console.log('next state', store.getState());
}
上面代码,就是对store.dispatch方法的简单扩展。
import {createStore, applyMiddleware, compose} from "redux"
export default function applyMiddleware(...middlewares) {
return (createStore) => (reducer, preloadedState, enhancer) => {
var store = createStore(reducer, preloadedState, enhancer);
var dispatch = store.dispatch;
var chain = [];
var middlewareAPI = {
getState: store.getState,
dispatch: (action) => dispatch(action)
};
chain = middlewares.map(middleware => middleware(middlewareAPI));
dispatch = compose(...chain)(store.dispatch);
return {...store, dispatch}
}
}
上面代码,对store.dispatch进行了扩展,关键在这一步dispatch = compose(...chain)(store.dispatch);
看看redux源码的compose实现:
/**
* Composes single-argument functions from right to left. The rightmost
* function can take multiple arguments as it provides the signature for
* the resulting composite function.
*
* @param {...Function} funcs The functions to compose.
* @returns {Function} A function obtained by composing the argument functions
* from right to left. For example, compose(f, g, h) is identical to doing
* (...args) => f(g(h(...args))).
*/
export default function compose(...funcs) {
if (funcs.length === 0) {
return arg => arg
}
if (funcs.length === 1) {
return funcs[0]
}
return funcs.reduce((a, b) => (...args) => a(b(...args)))
}
他借助了Array的reduce函数来实现,funcs列表里面的函数,都会被倒序依次调用。
看下面例子:
const f1 = (...arg) => {
console.log(arg, 'arg1')
return 1
}
const f2 = (...arg) => {
console.log(arg, 'arg2')
return 2
}
const f3 = (...arg) => {
console.log(arg, 'arg3')
return 3
}
compose(f1, f2, f3)('a', 'b', 'c')
// ["a", "b", "c"] "arg3"
// [3] "arg2"
// [2] "arg1"
拆分开来,他的执行过程是这样的:
funcs = [f1, f2, f3]
funcs.reduce((a, b) => (...args) => a(b(...args)))
// reduce执行过程
// loop1: a = f1, b = f2, ret1 = (...args) => f1(f2(...args))
// loop2: a = ret1, b = f3, ret2 = (...args) => ret1(f3(...args))
// 即 ret2 = (...args) => f1(f2(f3(...args)))
可见将函数列表像一个洋葱一样包起来执行。 所以我们可以自定义很多middleWare
store = createStore(
reducers,
applyMiddleware(ReduxThunk, logger, oth1, ...),
)
只需要我们按照规则定义:
const logger = store => next => action => {
console.log('prev state',store.getState())
console.log('dispatch',action);
let result = next(action);
console.log('next state',store.getState());
return result;
}
redux 中改变 state 的基本步骤是,dispatch 触发 action,然后通过 reducer 重新计算新的 state。
中间件本质上就是为 dispatch 这个方法添加一些附加操作,比如打印日志,异步操作等。
以日志中间件为例,为每个 dispatch 加日志: