1. redux-thunk
// store/index.js
import { createStore, applyMiddleware, compose } from "redux";
import reducer from "./reducer";
import thunk from "redux-thunk";
const sagaMiddleWare = createSagaMiddleWare();
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose; // 这个是redux devtools
// applyMiddleware使用中间件
const store = createStore(
reducer,
composeEnhancers(applyMiddleware(thunk))
);
export default store;
// store/reducer.js
import { combineReducers } from "redux";
import { countReducer } from "./count";
import { asyncReducer } from "./async";
// reducer的拆分
const reducer = combineReducers({
countInfo: countReducer,
asyncInfo: asyncReducer,
});
// combineReducers的原理如下,combineReducers多做了state的优化,如果没有改变就返回原来的,不会像下面一直返回的是新的{}
// reducer最后是一个函数,函数的返回值是一个对象
// function reducer(state={},action) {
// return {
// countInfo: countReducer(state.countInfo,action),
// asyncInfo: asyncReducer(state.asyncInfo,action)
// }
// }
export default reducer;
// store/async/index.js
import asyncReducer from "./reducer";
import * as asyncAction from "./action";
import * as asyncConst from "./constant";
export { asyncReducer, asyncAction, asyncConst };
// store/async/constant.js
export const BANNER= "BANNER";
export const RECOMMEND= "RECOMMEND";
export const SAGADATA= "SAGADATA";
// store/async/action.js
import { BANNER, RECOMMEND, SAGADATA } from "./constant";
import { asyncFn } from "@/api";
export const getBanner = (banner) => ({ type: BANNER, banner });
export const getRecommend = (recommend) => ({ type: RECOMMEND, recommend });
// redux-thunk的使用
// 原理就是传入的action是个函数,判断typeof如果是function就进行拦截
// 拦截后执行这个函数,并将dispatch和store.getState当做参数传入
export const getAsyncData = (dispatch, getState) => {
asyncFn.getMulti().then((res) => {
const data = res.data.data;
dispatch(getBanner(data.banner.list));
dispatch(getRecommend(data.recommend.list));
});
};
export const getSagaData = () => ({ type: SAGADATA, name: "666" });
// store/async/reducer.js
import { BANNER, RECOMMEND } from "./constant";
const asyncInfo = {
banner: [],
recommend: [],
};
// reducer是纯函数 结合state和action,返回新的state
function changeCounter(state = asyncInfo, action) {
switch (action.type) {
case BANNER:
return { ...state, banner: action.banner };
case RECOMMEND:
return { ...state, recommend: action.recommend };
default:
return state;
}
}
export default changeCounter;
// redux-thunk的使用页面
import React, { Component } from "react";
import { connect } from "react-redux";
import { asyncAction } from "./store/async";
export class TThunk extends Component {
componentDidMount() {
this.props.getData();
}
render() {
const { banner, recommend } = this.props;
return (
<div>
<hr />
<h4>redux-thunk的使用</h4>
<ul>
{banner.map((ban) => (
<li key={ban.acm}>{ban.title}</li>
))}
</ul>
<hr />
<ul>
{recommend.map((red) => (
<li key={red.acm}>{red.title}</li>
))}
</ul>
</div>
);
}
}
const mapStateToProps = (state) => ({
banner: state.asyncInfo.banner,
recommend: state.asyncInfo.recommend,
});
const mapDispatchToProps = (dispatch) => ({
getData() {
dispatch(asyncAction.getAsyncData);
},
});
export default connect(mapStateToProps, mapDispatchToProps)(TThunk);
2. generator的使用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<script>
// 生成器函数
function* test() {
console.log(1);
const r1 = yield "hello";
console.log(r1);
const r2 = yield "world";
console.log(r2);
const r3 = yield "666";
console.log(r3);
}
// 迭代器
const it = test(); //执行生成器,会返回迭代器,不会执行里面的内容
const it1 = it.next(); // 使用一次next,就消耗一次迭代器
console.log(it1);
const it2 = it.next("返回值"); //传入参数,会作为返回值
console.log(it2);
const it3 = it.next();
console.log(it3);
const it4 = it.next();
console.log(it4);
// generator和promise的使用
function* getData() {
const res = yield new Promise((resolve) => {
setTimeout(() => {
resolve("hello promise");
}, 2000);
});
console.log(res);
}
const itp = getData();
// itp.next()返回的是Promise,然后执行到2s后,执行最后一个next,把值传进去,作为参数,会返回给res
itp.next().value.then((msg) => {
itp.next(msg);
}); // 执行结果:hello promise
</script>
</body>
</html>
3. redux-saga的使用
// store/index.js
import { createStore, applyMiddleware, compose } from "redux";
import reducer from "./reducer";
import thunk from "redux-thunk";
import saga from "./saga"; // 业务saga的generator汇总
import createSagaMiddleWare from "redux-saga";
const sagaMiddleWare = createSagaMiddleWare();
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose; // 这个是redux devtools
// applyMiddleware使用中间件
const store = createStore(
reducer,
composeEnhancers(applyMiddleware(sagaMiddleWare, thunk))
);
sagaMiddleWare.run(saga); // saga运行,监听哪些action generator
export default store;
// store/saga.js
import { all, takeLatest, call, put } from "redux-saga/effects";
import { asyncAction, asyncConst } from "./async";
import { asyncFn } from "../../api";
function* getMultiData(action) {
// 这里判断是否是Promise,然后it.next().value.then((res)=>{it.next(res)}); 这样返回值就能获取到
const res = yield call(asyncFn.getMulti, { name: action.name });
const dt = res.data.data;
// 多个处理方式
yield all([
put(asyncAction.getBanner(dt.banner.list)),
put(asyncAction.getRecommend(dt.recommend.list)),
]);
}
// 监听action generator,每次dispatch(SAGADATA)会进行拦截,执行getMultiData generator
function* watchData() {
// 多个SAGADATA一起执行时候,takeLatest会拦截最后一个,takeEvery则是每个都执行
yield takeLatest(asyncConst.SAGADATA, getMultiData);
}
export default function* rootSaga() {
// 多个处理方式
yield all([watchData()]);
}
// redux-saga的使用页面
import React, { Component } from "react";
import { connect } from "react-redux";
import { asyncAction } from "./store/async";
export class TSaga extends Component {
componentDidMount() {
this.props.getData();
}
render() {
const { banner, recommend } = this.props;
return (
<div>
<hr />
<h4>redux-saga的使用</h4>
<ul>
{banner.map((ban) => (
<li key={ban.acm}>{ban.title}</li>
))}
</ul>
<hr />
<ul>
{recommend.map((red) => (
<li key={red.acm}>{red.title}</li>
))}
</ul>
</div>
);
}
}
const mapStateToProps = (state) => ({
banner: state.asyncInfo.banner,
recommend: state.asyncInfo.recommend,
});
const mapDispatchToProps = (dispatch) => ({
getData() {
dispatch(asyncAction.getSagaData());
},
});
export default connect(mapStateToProps, mapDispatchToProps)(TSaga);