Redux浅析



  • redux介绍
    可以理解为一种web的状态管理机制,其大致哲学就是要求数据->component之间的关系,常常和redux一起常常出现共同使用,但是其实也可以单独使用,用的技术比较原生所以还ok。

    首先react中使用redux的主要原因是因为react的组建之间通信代码的整洁性,比如子父组件的通信:
    0_1543196197393_e98dc524-3253-4847-84b8-28d938b76517-image.png Parent

    0_1543196263398_15458514-b049-4020-aeb9-7df5c0d6ba16-image.png Child

    如果在一个复杂的项目tree中可能有兄弟组件的通信等等问题,那么redux可以用来起简化操作的作用,毕竟是reduce是减少的意思嘛,redux大概就是减少操作流程的意思了。

    替代文字

    根据Redux Flow的原理,其实很清晰,大概就是普通的flux设计模式,即只需要是把dispatch改变store,每一个同步事件+异步事件结束之后把其同步到state中,就把关于数据的控制权交给了React了。

    代码就可以写成这样了

    import React, { Component } from 'react';
    import './App.css';
    import Test from "./Test";
    import { connect } from "react-redux";
    import {change} from "./action.js"
    
    //把state里面的值注入到connect中
    // const mapStateToProps = state => ({
    //   a: state.rootReducer
    // });
    const mapStateToProps = state => {
      return {
        a: state.changeStore
      }
    }
    
    //把action注入到props中
    const mapDispatchToProps = dispatch => ({
      change: num => dispatch(change(num))
    })
    
    
    //Parent
    class App extends Component {
      constructor(props) {
        super(props);
      }
    
      render() {
        return (
          <div className="App">
            {this.props.a}
            <Test/>
            <button onClick={()=>{
              console.log(1);
              this.props.change(12);
            }}>test
              </button>
          </div>
        );
      }
    }
    
    
    export default connect(
      mapStateToProps,
      mapDispatchToProps
    )(App)
    

    其实相当于一个装饰器的设计模式,可以用ES7的设计模式,但是懒得装babel插件~用装饰器模式代码会简洁不少。


    源码
    0_1543373182933_5aeb97f6-7875-43bb-a221-3e6824246e02-image.png

    可以看看redux的源文件可以说是代码各个文件都相当的简洁了,其中index.js就是一个export各个接口的闭包过程


    0_1543373313515_4b2ee7dd-8045-4d7d-a88a-2ef41f0c2380-image.png

    Compose.js

    其中compose.js主要是一个工具代码,会在之后的逻辑文件中调用,起大致作用就是代码组合的作用,比如把函数f(), g(), 和 h() 组合起来可以得到复合函数 f(g(h()))的作用,一个简单的测试程序
    0_1543374769265_f691e1de-6436-433e-b0ea-d92ac3c73fa8-image.png
    可以看出该函数是先执行test2再执行test1,是一种很常见的函数式编程的思想,在Redux中主要是用来做中间件的作用,中间件其实可以用多种方法实现(也有递归等方法,比如koa2的实现方法)


    createStrore.js

    这个是创建store的关键Function,可以先focus这个函数的返回值
    0_1543399380915_2aa0f4d5-3728-4c57-b7d6-7b3f3ae556cc-image.png

    其实我们主要用到的是前3个方法,所以主要关注这个就好了

    dispatch
    工作是连接action到reducer,其本质就是提供唯一一个可以修改store内的数据的方法,这一点符合React的设计模式(不可以直接修改state中的值)
    0_1543399681023_d7df522c-6507-4972-b768-2f5b216e7255-image.png
    其实dispatch的参数只有一个action的Object,前面的代码都是进行异常处理的,所以写代码也应该把对于参数的处理放在函数的前面,可以看出逻辑代码也很简单的,首先注明开始dispatch的状态,然后让action和当前的currentState中放到reducer中进行merge,最后修改currentState的状态;之后把每一个订阅者(listener)都唤醒一遍,最后返回这个action的值

    getState

    0_1543399990416_b944d63c-cc20-47da-a8f3-a0d0f0461474-image.png

    其实这个方法起了两个作用,第一个是保证了store的属性只可读性,第二个就是如果不允许在执行dispatch的时候读取store属性,虽然按照道理来说dispatch这个过程应该是一个阻塞的过程,所以这个场景我暂时没有想到

    subscribe

    这个作用是订阅数据在dispatch的过程之后,产生listener的作用,应该在react-redux这个库中是很常见的功能,就是一个简单的观察者模式(设计模式中)


    applyMiddleware.js

    0_1543400581009_018cc78d-22f9-47a3-82ac-233278edc9ab-image.png

    这个功能就是为Redux的开发过程增加中间件这个属性,其实他的原理就是修改了dispatch这个函数的功能,从而可以达到原生,dispatch并不可以达到的功能。
    首先复习一下applyMiddleware这个玩意怎么写
    0_1543401284030_d331574c-fb55-4d8a-9b6b-15402ae9769e-image.png

    这里就必须回到createStore.js这个处理中了
    0_1543401462467_ef473dd9-4f9a-42c6-a862-5da405496894-image.png

    0_1543401469309_fac495cb-f6b2-42ac-b186-c00d6c79bf28-image.png

    把它翻译成中文就是:

    如果createStore有enhancer这个参数,并且enhancer的类型是一个function,那么就不会返回虾米拿到闭包,而是调用这个enhancer这个方法了。所以这就是applyMiddleware中可以拿到createStore以及调用createStore这个函数的参数了(reducer, preloadedState),接下来的操作就很简单了,东西都拿到了链式调用就可以了
    0_1543402138329_2a53fcdb-db1e-4455-b616-64b38494f8b5-image.png

    当然了也有些trick就是把dispatch和getState这两个api打包给了中间件

    最后就是一个小的中间件DEMO啰,可以看出了虽然dispatch这个东西好用,但是只是一个同步的操作,设想一下如果我写的action中的这个数据是一个异步才可以拿到的数据,但是dispatch是一个同步的事件,那么去执行的时候,肯定会和预期有差别,那么一个facebook的大佬写了下面的中间的代码~

    0_1543402608353_e5927ecf-bb63-4366-b3bf-86f7595d76aa-image.png
    10000个赞了23333
    0_1543402641742_f092d864-ecd8-4b24-9446-f67d8ab8cf73-image.png

    其实代码很简单只有几行,可以看出来这里面就有我们的dispatch啊,getState,next就是要传递的修改厚度disptach方法啰,这样action所返回的值就可以不仅仅只有是object了还可以返回一个Fun。tion了,异步问题也就解决了~



  • 感觉很牛皮


 

Copyright © 2018 bbs.dian.org.cn All rights reserved.

与 Dian 的连接断开,我们正在尝试重连,请耐心等待