这可能是目前对redux最通俗的解释了

最近在学习react全家桶,于是在网上搜了很多资料,做了很多demo。终于明白了redux是一个什么东西了。

一、为什么要用redux

每一个工具的出现都是为了解决某一个痛点,react的痛点就是繁琐的props和state操作,举个例子:A主页下有个工具栏B,工具栏B下有个按钮,按钮可以更新控件D,但只能通过A->C->D,这个时候如果想要点击B下的按钮更新D,需要将数据作为props从A传到C传到D,然后再在A中写一个函数用来更新这个state,然后把这个函数作为props传入B,作为按钮的点击事件。

由于操作实在过于复杂,你想到能不能直接在B中修改D的state呢?于是redux就诞生了,当然,redux并不是让你能从B组件直接更改D的state,而是通过更改公共state,改完之后再通知D去更新state。下面举个例子说明这个过程。

二、通俗易懂的例子

那么什么是公共state,如何修改公共state呢?到这里,你在别的地方应该已经看到了什么action,纯函数,reducer之类的东西了,如果你还是不懂,请看下面这个例子。

假设你(组件B)的银行账户上有500元(公共state),你想将其中的100元转到别的地方(比如支付宝),且你和你的女朋友(组件D)同时订阅了这个账户的短信提醒。这时,你是不可能直接去银行然后操作银行电脑进行转钱的(不能直接修改公共state),假设你由于感冒了不能说话,于是你只能走到柜台前,递给操作员(reducer)一个条子(action),写着:

操作类型:转账
金额: 100
目的地:支付宝

你把这个字条递给操作员,然后操作员开始更新你的余额,更新完成之后短信提醒你和你的女朋友state已经更新了,然后你的女朋友就知道你的余额从500变成400了。

三、例子代码化

那么如何用代码实现这个流程呢?

首先我们来看银行的工作,银行就是reducer,它能支持各种各样的操作(action),现在我们把这个操作写出来。

bankReducer.js

export const actionTypes = {
  转账: "转账",
  存钱: "存钱",
  取钱:"取钱" 
}
const initialState = {
  余额: 500
};

现在我们有了三个操作,分别是转账,存钱和取钱,然后我们需要定义一个reducer函数,来告诉操作员当遇到这些actionType的时候分别做什么处理

export function reducer(state = 初始值, 操作) {
  switch (操作.type) {
    case actionTypes.存钱:
      return {
        余额: state.余额+action.存入金额
      };
    case actionTypes.取钱:
      return {
        余额: state.余额-action.取出金额
      },
     case actionTypes.转账:
      return {
        余额: state.余额-action.转账金额
      };
}

现在,当操作员拿到用户递过来的纸条的时候就能进行相应的操作了,但是用户能进行什么样的操作呢?于是银行还应该提供一些接口,告诉用户可以进行哪些操作:

扫描二维码关注公众号,回复: 15970771 查看本文章
export const actions = {
 存钱_操作: function(存入金额) {
   return {
     type: actionTypes.存钱,
     存入金额
    };
  },
 取钱_操作: function(取出金额) {
   return {
     type: actionTypes.取钱,
     取出金额
    };
  },

 转账_操作: function(转账金额) {
   return {
     type: actionTypes.转账,
     转账金额
    };
  },
}

让我们再重新梳理一下整个流程,用户首先填写信息到action,你可以理解为用户写了一个小纸条,比如转账,那么用户可以这样调用:

转账_操作(100)

那么function生成的小纸条就是

{
  type: actionType.转账,
  100
}

然后这个小纸条就会自动递给操作员(reducer,是的,你不用管是怎么给reducer的),然后操作员看到这个action的type是转账,那么进入转账操作:

case actionTypes.转账:
      return {
        ...state,
        余额: state.余额-action.转账金额
      };

这时,你的余额就更新为400了。

好了,现在整个银行都完成了,我们来看用户的部分,也就是你

you.jsx

首先我们需要一个按钮,按一下就转账100,怎么实现呢?

class You extends Component {
  constructor(props) {
    super(props);
    this.state = {
      余额: 0
    };
  }
  onClick = (e)=>{
    //点击之后进行转账
  }
  render() {
    return <Button onClick={this.onClick}>一键转账</Button>
  }
}

有人可能会问,为什么这里余额是0?因为余额需要银行统一通知,而不是自己设置的,那么现在就与要把你和银行连接起来,使得你能将小纸条递给操作员,也能收到银行的消息:

于是你就能看到之前头疼的两个函数了:mapStateToProps和mapDispatchToProps,那这两个函数作用是什么呢?

mapStateToProps:将银行的state更新到本地

mapDispatchToProps: 让你能使用银行提供的操作接口

先说mapStateToProps,我们现在state中只有“余额”这一个属性,但是实际上公共state中可能有很多其他的属性,比如

const initialState = {
  余额: 500,
  行长姓名: 颜小四,
  银行地址: 佐家垄职业技术学院旁的螺狮粉店里,
  ...
};

这些信息可能其他组件关系,但是你并不关心,所以当你更新本地state的时候,只需要更新余额就行了

function mapStateToProps(state) {
  return {
    余额: state.余额,
  };
}

这个函数的意思是,当我账户中余额属性更新时,同步到我的组件属性里(想要更新UI,需要调用componentWillReceiveProps,并在里面调用setState)

同样,银行可能提供很多操作,但是我只关心“转账”操作,于是可以只将转账操作映射过来,然后“我要转账”会作为函数,存在this.props里,调用方式为this.props.我要转账(注意这个函数的参数是与银行中的action参数一致的,转账操作的参数为“转账金额”):

import { actions as bankActions } from "bank.js";
function mapDispatchToProps(dispatch) {
  return {
   我要转账: bindActionCreators(bankActions.转账_操作, dispatch),
 };

现在,准备工作完了,将你和银行连接即可

export default connect(
  mapStateToProps,
  mapDispatchToProps
)(You)

这样你就成功地与银行连接了,你能调用银行的给出的接口了。现在,如果我们就能写onClick函数了,点击之后写入小纸条(action),纸条会自动交给操作员(reducer)更改你的余额(state)。

onClick = (e)=> {
  this.props.我要转账(100) //填写转账小纸条,写入转出金额为100
}

现在你已经能操作银行了,那怎么让女朋友也接受到通知呢?首先我们定义女友这个组件:

notExist.jsx

class notExist extends Component {
  constructor(props) {
    super(props);
    this.state = {
      余额: 0
    };
  }
  render() {
    return <h1>{this.state.余额}</h1>
  }
  function mapStateToProps(state) {
    return {
      余额: state.余额,
    };
  }  
  export default connect(
    mapStateToProps,
  )(notExist)
}

可以看到,我们只需要写好mapStateToProps, 并且connect到银行,那么你的女友就能收到通知了

结束语

感觉写了很多了,至少我是明白了。

猜你喜欢

转载自blog.csdn.net/weixin_44414901/article/details/118937719