前言
在前面的基础篇,我们学习了一些
redux的基础使用和基本方法的实现,但是这些基础的使用并不能满足我们的日常开发的需要,本文将给大家带来一些更高级的用法与实现。
高级使用
applyMiddleware
在开发的过程中往往我们需要在
dispatch之前增加一些自己的代码逻辑,也就是需要我们使用中间件,在redux的设计中就考虑到了这个事情,所以为我们提供了applyMiddleware这个方法。
中间件思想模拟(aop切片思想)
- 【1】保存原有的
dispatch方法 - 【2】重写
store中的dispatch方法 - 【3】在重写的
dispatch方法中插入自己的逻辑 - 【4】在重写的
dispatch方法中执行保存的原有dispath方法
注:本文依然使用基础篇中的
React实现源码继续讲解
/**
* store/index.js
*/
import { createStore } from 'redux';
import reducers from './reducers';
const store = createStore(reducers);
/*【1】保存原有的dispatch方法*/
const middleWare = store.dispatch;
/*【2】重写store中的dispatch方法*/
store.dispatch = function(action){
/*【3】在重写的`dispatch`方法中插入自己的逻辑*/
console.log('老状态',store.getState());
/*【4】在重写的`dispatch`方法中执行保存的原有`dispath`方法*/
middleWare(action);
/*【3】在重写的`dispatch`方法中插入自己的逻辑*/
console.log('新状态',store.getState());
}
export default store;
实战中间件
通过上一小节的讲解我觉得大家应该都明白中间件的作用和基本的思想了,当然在我们的真正开发中我们的中间件肯定不会像现在这样写的豪无逼格,下面我以实例为大家讲解
/**
* store/logger.js
*/
const logger = ({getState,dispatch})=>next=>action=>{
console.log('老状态(applyMiddleware)',getState());
next(action);
console.log('新状态(applyMiddleware)',getState());
}
export default logger;
/**
* store/index.js
*/
import { createStore,applyMiddleware } from 'redux';
import reducers from './reducers';
import logger from './logger';
const store = applyMiddleware(logger)(createStore)(reducers);
export default store;
- 看到这里我相信大家一定是很迷惑,为什么就这样执行了呢?那么我们就一起来分析一下这个
applyMiddleware的执行过程,并实现一下- 【1】
applyMiddleware传入一个中间件执行返回一个函数(fn1) - 【2】返回的函数(
fn1)传入createStore执行又返回函数(fn2) - 【3】返回的函数(
fn2)传入reducers执行返回store
- 【1】
function applyMiddleware(middleware) {
/*【1】applyMiddleware传入一个中间件执行返回一个函数(`fn1`)*/
return function fn1(createStore) {
/*【2】返回的函数(`fn1`)传入`createStore`执行又返回函数(`fn2`)*/
return function fn2(reducers) {
/*【3】返回的函数(`fn2`)传入`reducers`执行返回`store`*/
const store = createStore(reducers);
return store;
}
}
}
上图为应用到目前为止我们实现的
applyMiddleware的截图,可以看到除了我们的中间件logger没有效果其他逻辑是可以跑通的,因此证明我们的方向是正确的,所以我们结合logger继续完善
- 执行分析
logger(结合中间件思想模拟)- 【1】接收的参数可以解构出
getState和dispatch方法,返回fn1- 【1-1】回想一下我们基础篇中哪里有这个方法?没错就是创建的
store中
- 【1-1】回想一下我们基础篇中哪里有这个方法?没错就是创建的
- 【2】返回的
fn1接收参数next- 【2-1】通过最后的
next(action),我们再回想一下基础篇中的哪个方法执行需要传入action?对的,就是diapatch,这里我们可以先假象成这个next就是我们保存的原始dispatch
- 【2-1】通过最后的
- 【3】最后返回
action=>{native code},包装后的diapatch
- 【1】接收的参数可以解构出
function applyMiddleware(middleware){
return function(createStore){
return function(reducers){
const store = createStore(reducers);
let dispatch = ()=>{throw Error('还不能用')};
const middlewareAPI = {
getState:store.getState,
dispatch:(...args)=>dispatch(args)
}
middleware = middleware(middlewareAPI);
dispatch = middleware(store.dispatch);
return {
...store,
dispatch
};
}
}
}
结合我们的实现,结果如下
实现中间件的级联
上一小节中我们仅仅是实现了一个中间件的情况,也就是说当我们有很多事情想在
dispatch的时候想搞的时候显然我们需要多个中间件配合处理,当然你肯定想问,为什么不能把所有的事情放在一个中间件里面处理呢,这个也不是不可以,但是我们中间件的使用规则一般都是单一逻辑,也就是说一个中间件只处理一件事情,那么我们怎么将中间件级联起来呢?
- 使用示范
/*store/index.js*/
import { createStore,applyMiddleware } from 'redux';
import reducers from './reducers';
import logger from './logger';
import logger1 from './logger1';
const store = applyMiddleware(logger,logger1)(createStore)(reducers);
export default store;
/*store/logger.js*/
const logger = ({ getState, dispacth }) => next => action => {
console.log('老状态', getState());
next(action);
console.log('新状态',getState());
}
export default logger;
/*store/logger1.js*/
const logger1 = ({ getState, dispacth }) => next => action => {
console.log('老状态1', getState());
next(action);
console.log('新状态1',getState());
}
export default logger1;
function applyMilldeware(...middleware){
return function(createStore){
return function(reducers){
const store = createStore(reducers);
let dispatch = ()=>{thorw Error('不能用')}
const middlewareAPI = {
getState : store.getState;
dispatch : (..args)=>dispatch(args)
}
const chain = middlewares.map(middleware=>middleware(middlewareAPI));
dispatch = compose(...chain)(store.dispatch)
}
}
}