Redux原理分析

作者: 独爱一乐拉面 | 来源:发表于2017-03-09 23:31 被阅读104次

    redux介绍

    redux是一个针对JavaScript应用的可预测的状态管理器。

    redux中的设计模式

    装饰者模式

    定义:装饰者模式用于给对象动态地增加职责。

    我们来看看redux最早期(v0.2.0)的github代码:

    //Counter.js
    import React from 'react';
    import { performs, observes } from 'redux';
    
    @performs('increment', 'decrement','double')
    @observes('CounterStore')
    export default class Counter {
      render() {
        const { increment, decrement } = this.props;
        return (
          <p>
            Clicked: {this.props.counter} times
            {' '}
            <button onClick={() => increment()}>+</button>
            {' '}
            <button onClick={() => decrement()}>-</button>
            {' '}
            <button onClick={() => double()}>double</button>
          </p>
        );
      }
    }
    

    经过observes的包装后,react组件可以访问Redux store里的couter数据;经过performs的包装后,react组件可以发起increment、decrement和double这3个Action。

    我们来看看performs是怎么包装react组件的:

    //performs.js
    import React, { Component, PropTypes } from 'react';
    import pick from 'lodash/object/pick';
    import identity from 'lodash/utility/identity';
    
    const contextTypes = {
        getActions: PropTypes.func.isRequired
    };
    
    export default function performs(...actionKeys) {
        
        let mapActions = identity;
    
        return function (DecoratedComponent) {
            
            const wrappedDisplayName = DecoratedComponent.name;
    
            return class extends Component {
                static displayName = `ReduxPerforms(${wrappedDisplayName})`;
                static contextTypes = contextTypes;
    
                constructor(props, context) {
                    super(props, context);
                    this.updateActions(props);
                }
                
                updateActions(props) {
                    this.actions = mapActions(
                        pick(this.context.getActions(), actionKeys),
                        props
                    );
                }
    
                render() {
                    return (
                        <DecoratedComponent {...this.actions} />
                    );
                }
            };
        };
    }
    

    很简单对不对,performs实质上是一个高阶函数,接收一个react组件类型的参数DecoratedComponent,然后返回一个高阶组件,该组件包装了传递进来的react组件,并向该组件传递了action相关的props.

    Paste_Image.png Paste_Image.png Paste_Image.png

    通过可以看上面的图可以看出,Counter组件被Observes包装后,又被performs包装,形成了一条包装链。

    redux提供的API中,有一个重要的方法connect,用于连接 React 组件与 Redux store。连接操作不会改变原来的组件类,而是返回一个新的已与 Redux store 连接的组件类。典型的装饰者模式有木有?

    观察者模式

    定义:观察者模式又叫发布-订阅模式,它定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖它的对象都将得到通知。

    @observes('CounterStore')
    

    counter.js的这行代码表示它对Redux的CounterStore数据进行订阅。我们来看看objserves的实现:

    //observes.js
    import React, { Component, PropTypes } from 'react';
    import pick from 'lodash/object/pick';
    
    const contextTypes = {
        observeStores: PropTypes.func.isRequired
    };
    
    export default function connect(...storeKeys) {
    
        return function (DecoratedComponent) {
    
            const wrappedDisplayName = DecoratedComponent.name;
    
            return class extends Component {
                static displayName = `ReduxObserves(${wrappedDisplayName})`;
                static contextTypes = contextTypes;
    
                constructor(props, context) {
                    super(props, context);
                    this.handleChange = this.handleChange.bind(this);
                    this.unobserve = this.context.observeStores(storeKeys , this.handleChange); //订阅store数据
                }
                
                handleChange(stateFromStores) {
                    this.currentStateFromStores = pick(stateFromStores, storeKeys);
                    this.updateState(stateFromStores);
                }
                
                updateState(stateFromStores, props) {
                    stateFromStores = stateFromStores[storeKeys[0]];
                    const state = stateFromStores;
                    this.setState(state);//通过setState进行组件更新
                }
    
                componentWillUnmount() {
                    this.unobserve();//退订
                }
    
                render() {
                    return (
                        <DecoratedComponent {...this.props}
                            {...this.state} />
                    );
                }
            };
        };
    }
    

    当数据变化时,通过调用setState方法,进而对Counter组件进行UI更新。

    相关文章

      网友评论

        本文标题:Redux原理分析

        本文链接:https://www.haomeiwen.com/subject/xdufwttx.html