1、什么是redux的中间件
顾名思义中间件就是谁和谁之间,那么redux中间件中的中间指的是谁呢,其实指的就是action和store,那么action和store之间的桥梁是不是dispatch,所以redux的中间件就是对dispatch的一个封装,之前dispatch接收action的是一个对象,但是使用中间件之后还可以是一个函数,如果你使用了中间件,dispatch接收的是一个对象,它就会直接派发给store,但是如果接收到一个函数的话,dispatch就会先将函数处理完,处理好之后再派发给store。在这里处理啥呢,可以处理ajax异步请求等操作。redux中间件的流程图如下
2、常见的redux中间件
- redux-thunk: 解决redux中的异步问题,将异步问题放在action中进行操作。
- redux-saga:同样是解决redux中的异步问题,不同于redux-thunk的是,将异步问题的逻辑单独的拆分出来放到另一个文件进行管理。
3、 redux-thunk的使用
(1):安装redux-thunk
1:npm install redux-thunk --save
或
2:yarn add redux-thunk
(2):如果要做到一个从ajax获取的数据,替换store里的值,我们该怎么做呢,首先在组件中,componentDidMount生命周期内派发一个action给store,告诉store我们要做一个什么事情。
// 引入action文件中需要做的事情,这个事情我们自定义为getToDoList
import {getToDoList} from './storeThunk/actionCreators'
componentDidMount(){
const action = getToDoList()
store.dispatch(action)
}
(3):接下来我们就创建一个action文件actionCreators.js,在这里该文件是进行action操作的文件,redux-thunk也是在这体现出来的,可以将action返回一个函数,这里可以异步获取数据,再创建一个actionTypes.js,该文件是存放type类型的变量,对type类型进行管理。
actionTypes.js:
export const INIT_LIST_ACTION = 'init_list_action'
actionCreators.js
代码如下:
import {INIT_LIST_ACTION} from './actionTypes'
import axios from 'axios'
export const getInitListAction = (data) =>({
type:INIT_LIST_ACTION,
data
})
// redux-thunk的体现,返回一个函数
export const getToDoList = () =>{
return (dispatch) => {
axios.get('/todolist').then((res)=>{
console.log('res323',res)
const data = res.data
const action = getInitListAction(data)
dispatch(action)
})
}
}
(4):action需要store做的事情写好之后,我们需要在storeThunk文件夹(可自定义)下创建index.js,创建一个store,就可以使用store里的方法了,例如dispatch,再将我们安装的redux-thunk引入store,我们才可以像store派发一个action函数,代码如下:
// 创建一个store
import {createStore ,applyMiddleware ,compose} from 'redux'
import reducer from './reducer'
import thunk from 'redux-thunk';
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ ? window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({}) : compose;
const enhancer = composeEnhancers(
applyMiddleware(thunk)
);
const store = createStore(reducer,enhancer)
export default store
/**
* createStore:创建store
* store.dispatch() :帮我们派发action,action的内容会传递给store
* store.getState():获取store里的所有数据
* store.subscribe():订阅store的改变,只要store发生改变这个函数接收的回调函数就会被执行
*/
对以上出现的东西进行注解
- applyMiddleware :首先需要redux引入applyMiddleware ,这使得我们可以使用中间件
- composeEnhancers :这是可以使用redux-devtools插件的一个方法,需要查看点击链接,将redux-thunk引入进去的话,两个插件就可以一起使用了
(5):创建好store之后,引入的reducer文件,那我们在storeThunk下再创建一个reducer.js,这个文件是对store传过来的state和action进行处理。代码如下
import {INIT_LIST_ACTION} from './actionTypes'
const defalutState ={
defalutValue:'',
list:[]
}
// reducer是一个纯函数,给定固定的输入,就一定会有固定的输出,而且不会有任何的副作用
export default (state=defalutState,action)=>{
//将异步获取的数据action.data赋值给深拷贝的newState.list,在将新的对象return给store,store就获得一个新的数据了,改变之前的数据
if(action.type===INIT_LIST_ACTION){
const newState = JSON.parse(JSON.stringify(state))
newState.list = action.data
return newState
}
return state
}
4、 redux-saga的使用
那么使用redux-saga做异步获取数据来替换store里的数据怎么做呢,它也是对dispatch的封装,只不过将异步操作的部分跟action的部分单独分离一个文件出来,步骤如下
(1):安装redux-saga
1:npm install redux-saga --save
或
2:yarn add redux-saga
(2):在组件中,componentDidMount生命周期内派发一个action给store,告诉store我们要做一个什么事情。
// 引入action文件中需要做的事情,这个事情我们自定义为getToDoList
import {getInitList} from './storeThunk/actionCreators'
componentDidMount(){
const action = getInitList()
store.dispatch(action)
}
(3):同样需要创建一个action,创建一个action文件actionCreators.js,在这里该文件是进行action操作的文件
actionCreators.js
import {GET_INIT_LIST} from './actionTypes'
export const getInitList = () =>({
type:GET_INIT_LIST
})
actionTypes.js
export const GET_INIT_LIST = 'get_init_list'
(4):action创建好之后,redux-saga需要创建一个saga.js文件用来处理异步并派发action给store,看代码
// 引入redux-saga下的takeEvery 用来识别action中的type,
import { put, takeEvery } from 'redux-saga/effects'
import { GET_INIT_LIST } from './actionTypes'
import { getInitListAction } from './actionCreators'
import axios from 'axios'
function* getInitList() {
const res = yield axios.get('/todolist')
const action = getInitListAction(res.data)
yield put(action)
}
function* mySaga() {
yield takeEvery(GET_INIT_LIST, getInitList);
}
export default mySaga;
- takeEvery:第一个参数用来识别action中的type,第二个参数如果是自定义的函数,用来对这个type需要做的异步操作逻辑操作
- put :redux-saga下的函数,用来派发action,相当于dispatch,将action派发给store
- 这个文件中的函数都建议使用Generator函数
(5):action编写完之后,需要将action派发给store,所以我们来创建一个store,代码如下
index.js
// 创建一个store
import {createStore ,applyMiddleware ,compose} from 'redux'
import reducer from './reducer'
import createSagaMiddleware from 'redux-saga'
import toDoSaga from './saga'
const sagaMiddleware = createSagaMiddleware()
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ ? window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({}) : compose;
const enhancer = composeEnhancers(
applyMiddleware(sagaMiddleware)
);
const store = createStore(reducer,enhancer)
sagaMiddleware.run(toDoSaga)
export default store
- createSagaMiddleware:创建一个redux-saga,从而可以让我们使用redux-saga
- sagaMiddleware.run(toDoSaga): 创建好store之后,运行这句话,就可以将6saga文件中的action派发给store了
(6):创建好store之后,引入的reducer文件,那再创建一个reducer.js,这个文件是对store传过来的state和action进行处理。代码如下
import {INIT_LIST_ACTION} from './actionTypes'
const defalutState ={
defalutValue:'',
list:[]
}
// reducer是一个纯函数,给定固定的输入,就一定会有固定的输出,而且不会有任何的副作用
export default (state=defalutState,action)=>{
if(action.type===INIT_LIST_ACTION){
const newState = JSON.parse(JSON.stringify(state))
newState.list = action.data
return newState
}
return state
}
小总结
看了redux-thunk和redux-saga的使用步骤之后,是不是就可以很明显的看到两者的不同,redux-thunk将处理异步的操作和创建action写在一个文件里
而redux-saga是将action和处理异步的操作分开来管理
action:
saga: