react - redux 全局状态管理 、多组件共享状态 - 例子有详细注释

react全局状态管理

        • 基本概念
        • 下面开始小例子
          • 需要用到的插件redux
          • 代码 - 代码中有详细的注释
        • 参考
            • 阮一峰的网络日志

先来看一下Redux的流程图
react - redux 全局状态管理 、多组件共享状态 - 例子有详细注释_第1张图片

基本概念

  1. Store: 保存数据的地方,可以看成一个容器,一个应用只能有一个Store
  2. Store: 对象包含所有数据。如果想要得到某个时点的数据,就要对Store生成快照。这种时点的数据集合,就叫做State
  3. Action: 是一个对象。其中的type属性是必须的,表示Action的名称(下面会有例子),其他属性可以自由设置
  4. Action Creator: View要发送多少种消息,就会有多少种Action。如果都手写会很麻烦,可以定义一个函数来生成Action,这个函数就叫 actionCreator
  5. store.dispatch(): 是View发出Action的唯一方法
  6. Reducer: 是一个纯函数。 Store收到Action以后,必须给出一个新的State,这样View才会发生变化。这种State的计算过程就叫做Reducer
  7. store.subscribe(): Store允许使用store.subscribe()方法设置一个监听函数,一旦State发生变化,就会自动执行这个函数。

下面开始小例子

文件结构
react - redux 全局状态管理 、多组件共享状态 - 例子有详细注释_第2张图片

需要用到的插件redux
  • 先安装redux
    npm install redux --save
代码 - 代码中有详细的注释
  • app.js中只引入了Box组件,并且使用 所以就不做展示
    Box.js
import React, {
      Component, Fragment } from "react";
import Son1 from './Son1'
import Son2 from './Son2'

// Box 是容器组件 - 负责展示
function Box () {
     
  return (
    <Fragment>
      <Son1></Son1>
      <hr/>
      <Son2></Son2>
    </Fragment>
  )
}
export default Box

Son1.js

import React, {
      Component } from "react";
// 在需要使用到数据的组件中引入Store
import store from './Store/store'
import actionCreator from './Store/actionCreator'

class Son1 extends Component {
     
  componentDidMount() {
     
    // 使用subscribe监听reducer的改动.只要reducer中数据改变就会触发
    store.subscribe(() => {
     
      // 使用setState中只放一个空对象会更新所有的数据
      // 目的就是触发render的执行, 来重新渲染页面, 让页面的数据发生改变
      this.setState({
     })
    })
  }
  render () {
     
    // store下面有一个方法: getState() 获取到reducer下return的数据
    /* store组件中使用了reducer, 并返回了新的reducer
      reducer中返回的是state中的数据, 
    */
    let {
      name, age } = store.getState()
    return (
      <div>
        <h3>Son1 子组件</h3>
        <p>name: {
     name}</p>
        <p>age: {
     age}</p>
        <button
          onClick={
     () => {
     
            /* 调用actionCreator里面的changeName方法
              但是只调用这个方法数据是会改变, 但是页面数据不会
            改变
            */
            actionCreator.changeName()
          }}
        >修改名字</button>
      </div>
    )
  }
}
export default Son1

Son2.js: 和Son1.js几乎一样, 除了方法外

import React, {
      Component } from "react";
import store from './Store/store'
import actionCreator from "./Store/actionCreator";

class Son2 extends Component {
     
  componentDidMount () {
     
    store.subscribe(() => {
     
      this.setState({
     })
    })
  }
  render () {
     
    let {
      name, age } = store.getState()
    return (
      <div>
        <h3>Son2 子组件</h3>
        <p>name: {
     name}</p>
        <p>age: {
     age}</p>
        <button
          onClick={
     () => {
     
            actionCreator.changeAge(25)
          }}
        >修改年龄</button>
      </div>
    )
  }
}
export default Son2

store.js

// 从redux中引入createStore
/*
  createStore 接受reducer作为参数,生成新的Store.
以后每当store.dispatch发送过来一个新的Action就会自动
调用reducer, 得到一个新的State
*/
import {
      createStore } from 'redux'
import reducer from './reducer' // reducer组件
let Store = createStore(reducer) // 生成一个新的Store
export default Store

state.js: 用来存储全局共享数据,这个例子需要用到的数据比较少。所以比简陋

// State 全局状态管理数据
export default {
     
  name: '韩梅梅',
  age : 18
}

reducer.js

// reducer
/*
  reducer 本质是一个函数, 所以直接直接导出一个函数
  这个函数接受两个参数
  prevState: 修改前的数据
  actions: 是一个对象, 里面放着很多方法.
*/
import State from './state'
/* 给prevState一个默认值: State
为什么不直接把State作为参数?
  修改数据的时候只修改prevState, 不修改State中的数据
*/
export default (prevState = State, actions) => {
     
  // 创建一个新的数据, 赋值prevState
  let newData = prevState
  // 数据的修改
  // reducer 组件中接收到actionCreator中的action, 并解构出里面的属性
  let {
      type, payload } = actions
  // 使用switch方法, 判断调用的是哪个方法. 这时候就需要使用到type标识
  switch (type) {
     
    case 'CHANGE_NAME': // 判断type标识
      newData.name = payload // 修改newData中的name为action中传来的数据
      break;
    case 'CHANGE_AGE':
      newData.age = payload
      break;
    default:
      break;
  }

  // 返回的数据是修改后的数据, 也是getState()方法获取的数据
  return newData
}

actionCreator.js

// actionCreator 本质是一个对象. 这个对象里面有很多的方法
// 哪里需要调用这里面的方法, 就在哪个组件中引入actionCreator
import store from './store'
export default {
     
  changeName () {
      // 修改name的方法
    let action = {
      // action对象
      type: 'CHANGE_NAME', // type 标识: 必须的属性, 固定属性只能是type
      payload: '李雷雷' // 这是传递数据的参数
    }
    /* store.dispatch 是 View 发出 Action 的唯一方法。
    接受一个 Action 对象作为参数,将它发送出去。
    */
    store.dispatch(action)
  },
  changeAge (age) {
     
    let action = {
     
      type: 'CHANGE_AGE',
      payload: age // 可以使用参数
    }
    store.dispatch(action)
  }
}

效果
react - redux 全局状态管理 、多组件共享状态 - 例子有详细注释_第3张图片

参考

阮一峰的网络日志

你可能感兴趣的:(react,react)