zoukankan      html  css  js  c++  java
  • redux和react-redux的使用详解

    我自己的理解redux就跟vue中的vuex差不多,都是数据管理器,话不多说,我们从经典的计数器案例开始讲解

    使用redux实现计数器

    创建如下的react项目,我习惯把每一个模块分块,才有这么多文件,当然你也可以写在一个js文件中,这不是重点

    首先我们看一下项目的入口文件index.js

    import 'core-js/fn/object/assign';
    import React from 'react';
    import ReactDOM from 'react-dom';
    import Counter from './components/Counter'; //引入计数器件
    import {createStore} from 'redux'; //通过解构赋值得到createStore,为store的创建做准备
    import reducer from './reducers/index' //引入reducer纯函数 该函数,根据action的type不同结合旧的state返回新的state
    let store = createStore(reducer); //创建redux的核心 store store我会在后面进行详细的解答
    import {numAdd,numDel} from './actions/index'; //引入action函数,触发什么操作,就根据操作怎样改变值
    
    // Render the main component into the dom
    //这里使用Redducer变量来定义ReactDOM中的render函数,是方便store中state更新之后,页面的渲染
    const Redducer = () =>{
      ReactDOM.render(
        <Counter     
          value={store.getState()} 
          add ={()=>store.dispatch(numAdd())}
          del ={()=>store.dispatch(numDel())}
        ></Counter>,
        document.getElementById('app')
      );
    };
    // value={store.getState()} 给展示组件Counter传递数据 这里的store.getState()得到的值,就是store创建过程中reducer纯函数里面的初始state值
    // ()=>store.dispatch(numAdd())和()=>store.dispatch(numDel()) 定义函数传递给展示组件Counter
    //store.dispatch(参数)会传递一个对象作为参数例如{type:"add"},调用reducer纯函数,实现store中的state的更新
    
    Redducer();//该函数执行,就初始化了页面
    
    store.subscribe(Redducer);
    //store.subscribe()用来监听store中大的state是否发生改变,如果发生改变,就重新渲染页面,所以才跟Redducer()进行绑定

    在看纯函数reducer,至于为什么redux负责state编辑的函数统称reducer,我自己的猜测是根据es5中的reduce方法有关(纯属瞎猜测,切勿当真)

    const reducer = (state=0,action)=>{
      switch (action.type){
        case 'add':
          return state+1;
        case 'del':
          return state-1;
        default:
          return state
      }
    };
    //定义store的state = 0,action接受的值就是store.dispatch(numAdd())中通过numAdd()函数的到的一个对象
    //由于前面在得到store的时候 该函数跟redux中的createStore进行了绑定 也就是这一句代码 let store = createStore(reducer)
    //所以通过这里就可以改变store的state值,所以说现在可以的理解reducer为什么是一个纯函数了吧
    export default reducer;

    在看actions中的导出函数

    export const numAdd = ()=>{
      return{
        type:"add"
      }
    };
    export const numDel = ()=>{
      return{
        type:"del"
      }
    
    }
    //导出两个函数,每一个函数返回一个包含type属性的对象(注意ation中type是必须的,其他的属性可以自行添加),可以通过解构赋值得到每一个
    //的函数,就像入口文件index.js中的这一句代码 import {numAdd,numDel} from './actions/index';

    最后看展示组件Counter

    import React from 'react';
    //函数返回组件的话,就是解构赋值获取数据
    // const Counter = ({ value, add, del })=>{
    //   return(
    //    <div>
    //      <p style={{color:'red'}}>
    //        点击次数{value}
    //      </p>
    //      <button onClick={add}>加一</button>
    //      <button onClick={del}>减一</button>
    //    </div>
    //   )
    // };
    
    
    //class返回组件的话,就是直接获取当前组件自身的属性,就可以获取到自己想要的数据
    class Counter extends React.Component {
      render() {
        return (
          <div>
            <p style={{color: 'red'}}>
              点击次数{this.props.value}
            </p>
            <button onClick={this.props.add}>加一</button>
            <button onClick={this.props.del}>减一</button>
          </div>
        )
    
      }
    }
    export default Counter;

    在这里我使用了两种方式来创建组件,第一种通过函数的方式创建的组件,要获取在入口文件index.js中传过来的数据,只能通过形参解构赋值的到数据,第二种通过class创建的组件只能通过组件自身的属性,来获取数据,当然也可以通过解构赋值来得到自己想要的数据,代码如下

    class Counter extends React.Component {
      render() {
        let {value,add,del} = this.props;
        return (
          <div>
            <p style={{color: 'red'}}>
              点击次数{value}
            </p>
            <button onClick={add}>加一</button>
            <button onClick={del}>减一</button>
          </div>
        )
    
      }

    综上所有的代码就可以实现了简单的计数器的功能,这就是redux最基本的使用方法,提示:redux和reat-redux需要自己安装,最好使用--save来安装

    接下来就是使用redux和react-redux来实现计数器

    且看代码

    import React, { Component } from 'react' //引入react
    import PropTypes from 'prop-types' //引入限制UI组件(展示组件)属性限制
    import ReactDOM from 'react-dom' //引入react-dom相关的对象
    import { createStore } from 'redux' //引入redux
    import { Provider, connect } from 'react-redux'//引入react配套的redux
    
    // 创建react组件(或者是虚拟节点)
    class Counter extends Component {
      render() {
        const { value, onIncreaseClick } = this.props;
        //通过解构赋值得到相应的属性里面的值
        //在这里Counter是UI组件(展示组件)其属性是其外面的容器组件中的state是通过react-redux中的connect操作之后传递过来的
        return (
          <div>
            <span>{value}</span>
            <button onClick={onIncreaseClick}>Increase</button>
            {/*通过点击事件触发绑定的属性,很明显,在这里onIncreaseClick是一个方法或者是一个对象的key值,其映射的value值是一个函数*/}
          </div>
        )
      }
    }
    
    //对展示组件中属性各个值得类型进行限制 不合符规则会报错
    Counter.propTypes = {
      value: PropTypes.number.isRequired, //属性对象中的value必须是number类型还有必须有值
      onIncreaseClick: PropTypes.func.isRequired //属性对象中的onIncreaseClick必须是函数还有必须有值
    };
    
    // 这里定义的是一个action对象,我的理解就是跟vuex中actions的作用差不多,发送不同的动作名称,通过配套其他函数的监听
    //实现容器组件的状态(state)的改变,只不过vuex中的actions是发送动作名,redux是根据actions对象中的type的值不同,进行不同的操作
    
    const increaseAction = { type: 'increase' };
    
    // 定义reducer纯函数,reducer函数的作用就是,根据传过来的action和旧state的状态值
    //然后根据action的type的值进行不同的操作,进行新的state的返回,从而达到UI组件(展示组件)的重新渲染
    function counter(state = { count: 0 }, action) {
      const count = state.count;
      switch (action.type) {
        case 'increase':
          return { count: count + 1 };
        default:
          return state
      }
    }
    
    // 创建store对象,可以说store是redux的核心,因为根据redux的设计理念,
    //对state的操作都是根据store中的各种方法实现的,便于管理
    //在这里规定使用redux中的createStore和reducer纯函数结合来得到我们想要的store
    const store = createStore(counter);
    
    //mapStateToProps是connect的第一个参数
    //根据名称我们知道是把之前reducer纯函数中的state(状态)和展示组件的props(属性)进行映射
    function mapStateToProps(state) {
      return {
        value: state.count
      }
    }
    
    // mapDispatchToProps是connect的第二个参数
    //根据名称我们可以知道是把reducer纯函数中之前store中的dispatch方法和展示组件的props(属性)进行映射
    function mapDispatchToProps(dispatch) {
      return {
        onIncreaseClick: () => dispatch(increaseAction)
      }
    }
    
    // 这里定义App为react-redux设计理念中的容器组件
    //通过connect中传递参数和展示组件Counter相结合得出相应的容器组件App
    //这里的容器组件App里面包含了展示组件Counter
    const App = connect(
      mapStateToProps,
      mapDispatchToProps
    )(Counter);
    
    //向目标元素渲染容器组件App
    //这里的组件Provider是一个react-redux中特殊的组件
    //注意: 1. Provider中有且只有一个子组件(这里就是App容器组件,不一定是容器组件,根据自己的业务需求自己操作)
    //      2. 使用Provider组件的好处是,只需要给Provider组件设置属性,那么其子组件和其子组件中的子组件都可以直接使用其对应的属性
    //      3. 避免了组件嵌套之后一个一个传递的复杂操作
    ReactDOM.render(
      <Provider store={store}>
        <App />
      </Provider>,
      document.getElementById('app')
    )

    在这里就完成了redux和react-redux的结合使用,通过自己的学习,我发现了编程思想是多么的重要,我感叹于react-redux这种思想的深度,整体感觉干净,使得展示组件和容组件既相互分离又有一定的结合,兼职就是藕断丝连,但是又不会违背组件分离的思想,简直就是强大

    ,好了基础的redux和react-redux的讲解就到此结束了,后面我还会写出redux异步编程的理解,毕竟现在的都是同步实现

    累积知识点,解决每一个遇到的问题,实现从量变到质变
  • 相关阅读:
    monkeyrunner 进行多设备UI测试
    python Pool并行执行
    python 字符串函数
    python Map()和reduce()函数
    python re模块使用
    3.6 C++继承机制下的构造函数
    3.5 C++间接继承
    3.4 C++名字隐藏
    3.3 C++改变基类成员在派生类中的访问属性
    3.2 C++继承方式
  • 原文地址:https://www.cnblogs.com/jsydb/p/9480216.html
Copyright © 2011-2022 走看看