Redux
redux的作用
redux的流程
需要的插件有
cnpm install redux react-redux redux-thunk --save-dev
vuex就一个,这里为什么要三个
- redux,相当于一个数据库,可以当成一个本地的数据库使用,提供【reducer(管理数据) action(执行动作) store(存储池)】,这是全局变量的插件,并不只是用在react框架上的
- react-redux,连接react和redux的工具,完成数据订阅
- redux-thunk,可以实现异步的action
正式内容
- 不管是redux还是vuex都应该分模块去写,下面展示的是production模块的使用
- store/production/action-type.js
// 保存商品数据
export const GETPRODUCTION = 'GETPRODUCTION';
// 选择商品
export const TOGGLESELECT = 'TOGGLESELECT';
// 编辑商品
export const EDITPRODUCTION = 'EDITPRODUCTION';
// 清空选择
export const CLEARSELECTED = 'CLEARSELECTED';
- store/production/action.js
import * as pro from './action-type';
import API from '@/api/api';
// 初始化获取商品数据,保存至redux
export const getProData = () => {
// 返回函数,异步dispatch
return async dispatch => {
try{
let result = await API.getProduction();
result.map(item => {
item.selectStatus = true;
item.selectNum = 0;
return item;
})
// 这里执行的dispatch是同步修改redux的数据的方法
dispatch({
type: pro.GETPRODUCTION,
dataList: result,
})
}catch(err){
console.error(err);
}
}
}
// 选择商品
export const togSelectPro = index => {
return {
type: pro.TOGGLESELECT,
index,
}
}
// 编辑商品
export const editPro = (index, selectNum) => {
return {
type: pro.EDITPRODUCTION,
index,
selectNum,
}
}
// 清空选择
export const clearSelected = () => {
return {
type: pro.CLEARSELECTED,
}
}
- store/production/reducer.js
import * as pro from './action-type';
import Immutable from 'immutable';
let defaultState = {
/**
* 商品数据
* @type {Array}
* example: [{
* product_id: 1, 商品ID
* product_name: "PaiBot(2G/32G)", 商品名称
* product_price: 2999, 商品价格
* commission: 200, 佣金
* selectStatus: false, 是否选择
* selectNum: 0, 选择数量
* }]
*/
dataList: [],
}
// 下面也是使用了immutable插件,要知道为什么已经怎么使用,查看【react】笔记
// 这个暴露的方法规定就是第一个参数是state,第二个是action
// state是上面的defaultState,那action从哪来,往下看,在使用的部分
export const proData = (state = defaultState, action) => {
let imuDataList;
let imuItem;
switch(action.type){
case pro.GETPRODUCTION:
return {...state, ...action}
case pro.TOGGLESELECT:
//避免引用类型数据,使用immutable进行数据转换
imuDataList = Immutable.List(state.dataList);
imuItem = Immutable.Map(state.dataList[action.index]);
imuItem = imuItem.set('selectStatus', !imuItem.get('selectStatus'));
imuDataList = imuDataList.set(action.index, imuItem);
// redux必须返回一个新的state
return {...state, ...{dataList: imuDataList.toJS()}};
case pro.EDITPRODUCTION:
//避免引用类型数据,使用immutable进行数据转换
imuDataList = Immutable.List(state.dataList);
imuItem = Immutable.Map(state.dataList[action.index]);
imuItem = imuItem.set('selectNum', action.selectNum);
imuDataList = imuDataList.set(action.index, imuItem);
// redux必须返回一个新的state
return {...state, ...{dataList: imuDataList.toJS()}};
// 清空数据
case pro.CLEARSELECTED:
imuDataList = Immutable.fromJS(state.dataList);
for (let i = 0; i < state.dataList.length; i++) {
imuDataList = imuDataList.update(i, item => {
item = item.set('selectStatus', false);
item = item.set('selectNum', 0);
return item
})
}
return {...state, ...{dataList: imuDataList.toJS()}};
default:
return state;
}
}
store/store.js
import {createStore, combineReducers, applyMiddleware} from 'redux';
import * as production from './production/reducer';
import thunk from 'redux-thunk';
let store = createStore(
// 融合组件redux的方法
combineReducers({...production}),
// 添加中间件
applyMiddleware(thunk)
);
export default store;
- index.js
import {Provider} from 'react-redux';
import store from './store/store';
const render = Component => {
ReactDOM.render(
//绑定redux
<Provider store={store}>
// 热加载
<AppContainer>
<Component />
</AppContainer>
</Provider>,
document.getElementById('root'),
)
}
- 使用
// production/production.js
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { getProData, togSelectPro, editPro } from './store/production/action';
class Production extends Component{
state = {
}
clickTest(){
this.props.proData.dataList;
this.props.togSelectPro();
}
render(){
return ()
}
...
}
// 把redux数据在这里存入this.props对象里
// 这个connect传的就是上面的proData的两个参数state和action
export default connect(state => ({
// 这个state是指整个redux里存在的数据对象
// 这个key你想叫什么都行,最后会用这个key的名字把数据存放在this.props里
Key: state
// 这个state里的对象名是reducer.js里暴露的方法名
proData: state.proData,
}), {
// 这些是上面引入的action
// 写在这里就会被存放到this.props里
getProData,
togSelectPro,
editPro
})(Production);
// 不需要用redux的还是用下面的写法就行
// export default Production;
为什么数据会在props里
// 如果打印connect方法
function connect(mapStateToProps, mapDispatchToProps, mergeProps) {
// 第一个参数就是把state传到props
// 第二个参数就是把Dispatch传到props
}