-
回顾redux
- redux解决了什么问题
- redux基本架构图
- dispatch函数
-
如何编写中间件
- 中间件函数基本格式
- 中间件洋葱模型
-
redux中间件源码解析
- applyMiddleware函数
- compose函数
1. 回顾redux
-
redux解决了什么问题
-
一个react应用就是一颗组件树,react是单向数据流。单向数据流的情况下,组件之间数据如何通信?组件的公共数据应该放在哪里?
redux.png
-
-
redux基本架构图
-
dispatch函数
2. 如何编写redux中间件
- 中间件函数本质就是对dispatch方法的扩展,那么如何优雅的扩展dispatch方法?
- mid1,mid2,mid3分别为三个中间件函数,编写中间件函数有一个固定格式,必须按照以下格式编写
// getState获取当前state的状态
function mid1({ getState }) {
// next指向下一个要执行的(action) => {}匿名函数
return (next) => {
// action是指dispatch中的对象
return (action) => {
console.log('start mid1')
next(action)
console.log('end mid1');
}
}
}
// getState获取当前state的状态
function mid2({ getState }) {
// next指向下一个要执行的(action) => {}匿名函数
return (next) => {
// action是指dispatch中的对象
return (action) => {
console.log('start mid2')
next(action)
console.log('end mid2');
}
}
}
// getState获取当前state的状态
function mid3({ getState }) {
// next指向下一个要执行的(action) => {}匿名函数
return (next) => {
// action是指dispatch中的对象
return (action) => {
console.log('start mid3')
next(action)
console.log('getState() :', getState());
console.log('end mid3');
}
}
}
// 配置中间件
const middleware = [mid1, mid2, mid3]
// 创建store
const finalCreateStore = applyMiddleware(...middleware)(createStore)
-
触发一次dispatch后的执行结果
WechatIMG95log.jpeg -
中间件洋葱模型
-
当用户调用dispatch时,首先执行mid1中间件,在mid1中调用next执行mid2中间件,依次执行,最终调用dispatch,dispatch调用结束后,依次执行剩余中间件代码。
zIjmUzn.png
3. redux中间件源码解析
// 配置中间件
const middleware = [mid1, mid2, mid3]
// 创建store
const finalCreateStore = applyMiddleware(...middleware)(createStore)
-
applyMiddleware函数
function applyMiddleware(...middlewares) {
// createStore创建store调用的方法
return createStore => (...args) => {
const store = createStore(...args)
const chain = middlewares.map(middleware => middleware())
/*
chain: [
f1: (next) => (action) => { console.log('start mid1'); next(action); console.log('end mid1'); },
f2: (next) => (action) => { console.log('start mid2'); next(action); console.log('end mid2'); },
f3: (next) => (action) => { console.log('start mid3'); next(action); console.log('end mid3'); }
]
*/
dispatch = compose(...chain)(store.dispatch)
/*
dispatch = f1(f2(f3(store.dispatch)))
*/
return {
...store,
dispatch
}
}
}
-
compose
// (f1, f2, f3) -> (...args) => f1(f2(f3(...args)))
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)))
}
网友评论