加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

redux原理分析

发布时间:2020-12-15 07:30:44 所属栏目:百科 来源:网络整理
导读:redux介绍 redux是一个针对JavaScript应用的可预测的状态管理器。 redux中的设计模式 装饰者模式 定义:装饰者模式用于给对象动态地增加职责。 我们来看看redux最早期(v0.2.0)的github代码: //Counter.jsimport React from 'react';import { performs,obs

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.

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

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

观察者模式

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

@observes('CounterStore')

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

//observes.js
import React,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);
                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更新。

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读