Redux

笔记来自
redux
redux

redux的作用

image.png

redux的流程

image.png

需要的插件有

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
}
原文地址:https://www.cnblogs.com/pengdt/p/13070782.html