zoukankan      html  css  js  c++  java
  • Redux中的重要概念

    Action/Reducer/Store

    首先,先看看第一张图,图中展示了Redux的单向数据流,以及Action、Reducer和Store这三个核心概念。

    下面就围绕上图,非别介绍Action、Reducer和Store这三个概念。

    Action和Action Creator

    Action是一个对象,用来代表所有会引起状态(state)变化的行为(例如服务端的响应,页面上的用户操作)。

    假如我们要实现一个任务管理系统,那么添加任务的Action对象就会是下面的形式:

    {
        type: 'ADD_TASK',
        name: 'Read ES6 spec',
        category: 'Reading'
    }

    Action对象是行为的描述,一般都会包含下面的信息:

    • 一个字符串类型的type字段来表示将要执行的动作
    • 需要传递给应用的其他数据信息(例子中的name和category),数据形式用户可以自定义

    Action通过Action创建函数(Action Creator)来创建,Action Creator是一个函数,最终返回一个Action对象。

    对于添加任务这个行为,对应的Action Creator如下:

    复制代码
    function addTask(name, category) {
        return {
            type: ADD_TASK,
            name,
            category
        };
    }
    复制代码

    Reducer

    Action对象仅仅是描述了行为的相关信息,至于如何通过特定的行为来更新state,就需要看看Reducer了。

    关于Reducer,最简单的描述就是:

    • Reducer是一个函数
    • 该函数接收两个参数,一个旧的状态previousState和一个Action对象
    • 返回一个新的状态newState

    根据上面的描述,Reducer函数就可以表示为:

    (previousState, action) => newState

    Reducer函数的形式通常如下:

    复制代码
    function reducer(state = [], action) {
        // 处理不同action的代码
        switch (action.type) {
            case SPECIAL_ACTION:
                // 根据SPECIAL_ACTION action更新state
                // 返回新的state
            default:
                return state
        }
    }
    复制代码

    Store

    Actions描述了"what happened"的事实,Reducers则根据这些actions来更新state,而Store则是Actions和Reducers连接在一起的对象。

    Store是Redux中数据的统一存储,维护着state的所有内容,所以Store的主要功能就是:

    • 维护应用的state内容
    • 提供getState()方法获取 state
    • 提供dispatch(action)方法更新 state
    • 提供subscribe(listener)方法注册监听器

    看到Store提供的方法,就可以把Action、Reducer和Store联系在一起了:

    1. Store通过dispatch(action)方法来接收不同的Action
    2. 根据Action对象的type和数据信息,Store对象可以通过Reducer函数来更新state的内容

    Middleware

    下面就来看看第二张图,跟第一张图的差别不大,只是增加了中间件(Middleware)来处理Action。

    在Redux中,Middlerwares主要的作用就是处理Action,Redux中的Action必须是一个plain object。但是为了实现异步的Action或其他功能,这个Action可能就是一个函数,或者是一个promise对象。这是就需要中间件帮助来处理这种特殊的Action了。

    也就是说,Redux中的Middleware会对特定类型action做一定的转换,所以最后传给reducer的action一定是标准的plain object。

    针对Action的特征,Reudx Middleware可以采取不同的操作:

    • 可以选择传递给下一个中间件,如:next(action)
    • 可以选择跳过某些中间件,如:dispatch(action)
    • 或者更直接了当的结束传递,如:return。

    Redux中常用的中间件:

    • redux-thunk:action可以是一个函数,用来发起异步请求。
    • redux-promise:action可以是一个promise对象,用来更优雅的进行异步操作。
    • redux-logger:action就是一个标准的plain object,用来记录action和nextState的。

    react-redux

    经过前面的介绍,我们已经看到了Redux中的一些核心概念。Redux跟React没有直接的关系,本身可以支持React、Angular、Ember等等框架。

    通过react-redux这个库,可以方便的将react和redux结合起来:react负责页面展现,redux负责维护/更新数据状态。

    到这里,第三张图就展示了react-redux这个库的工作原理,react和redux是怎么联系到一起的。

    react-redux中提供了两个重要功能模块Provider和connect,这两个模块保证了react和redux之间的通信,下面就分别看看这两个模块。

    Provider

    通过Provider的代码可以看到,Provide本质上是一个react组件。

    复制代码
    export default class Provider extends Component {
      getChildContext() {
        return { store: this.store }
      }
    
      constructor(props, context) {
        super(props, context)
        this.store = props.store
      }
    
      render() {
        const { children } = this.props
        return Children.only(children)
      }
    }
    复制代码

    Provider组件主要用到了react通过context属性,可以将属性(props)直接给子孙component,无须通过props层层传递,从而减少组件的依赖关系。

    connect

    connect方法的主要作用就是让Component与Store进行关联, Store的数据变化可以及时通知Views重新渲染。

    任何一个通过connect()函数处理过的组件都可以得到一个dispatch方法作为组件的props,以及得到全局state中的所有内容。

    通过源码]可以看到,connect函数运行后,会返回一个wrapWithConnect函数,该函数可以接收一个react组件,然后返回一个经过处理的Connect组件。

    复制代码
    return function wrapWithConnect(WrappedComponent) {
      class Connect extends Component {
        constructor(props, context) {
          // 从祖先Component处获得store
          this.store = props.store || context.store
          this.stateProps = computeStateProps(this.store, props)
          this.dispatchProps = computeDispatchProps(this.store, props)
          this.state = { storeState: null }
          // 对stateProps、dispatchProps、parentProps进行合并
          this.updateState()
        }
        shouldComponentUpdate(nextProps, nextState) {
          // 进行判断,当数据发生改变时,Component重新渲染
          if (propsChanged || mapStateProducedChange || dispatchPropsChanged) {
            this.updateState(nextProps)
              return true
            }
          }
          componentDidMount() {
            // 改变Component的state
            this.store.subscribe(() = {
              this.setState({
                storeState: this.store.getState()
              })
            })
          }
          render() {
            // 生成包裹组件Connect
            return (
              <WrappedComponent {...this.nextState} />
            )
          }
      }
      Connect.contextTypes = {
        store: storeShape
      }
      return Connect;
    }        
    复制代码

    详细内容和demo

    文中很多Redux的概念都是进行了简单的介绍,更多详细的介绍可以参考,GitHub地址:WilberTian/StepByStep-Redux

    每篇文章的结尾都会有一些简单的demo 代码,帮助理解文章中介绍的内容。

    总结

    文中结合三张图片介绍了Redux中的一些核心概念,以及React和Redux之间通过react-redux这个库进行交互。

    更多详细的内容,已经整理到了GitHub上了(WilberTian/StepByStep-Redux),通过这些介绍以及demo的运行结果,一定能对Redux有一个比较基本的认识。

  • 相关阅读:
    Codeforces Round #595 (Div. 3) A,B,C,D
    计算几何板子题【2019牛客国庆集训派对day7——三角形和矩形】【多边形相交的面积】
    [POJ]POJ1753(dfs)
    [POJ]POJ2965(dfs)
    洛谷 P1772 [ZJOI2006]物流运输 题解
    简单概率与期望
    洛谷 P3802 小魔女帕琪 题解
    用树状数组实现的平衡树
    【模板】扩展中国剩余定理(EXCRT)
    新博客开通通知
  • 原文地址:https://www.cnblogs.com/axl234/p/5729072.html
Copyright © 2011-2022 走看看