redux原理分析

redux介紹

redux是一個針對JavaScript應用的可預測的狀態管理器。javascript

redux中的設計模式

裝飾者模式

定義:裝飾者模式用於給對象動態地增長職責。java

咱們來看看redux最先期(v0.2.0)的github代碼:react

//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。git

咱們來看看performs是怎麼包裝react組件的:github

//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.redux

Paste_Image.png

Paste_Image.png

Paste_Image.png

經過能夠看上面的圖能夠看出,Counter組件被Observes包裝後,又被performs包裝,造成了一條包裝鏈。設計模式

redux提供的API中,有一個重要的方法connect,用於鏈接 React 組件與 Redux store。鏈接操做不會改變原來的組件類,而是返回一個新的已與 Redux store 鏈接的組件類。典型的裝飾者模式有木有?app

觀察者模式

定義:觀察者模式又叫發佈-訂閱模式,它定義對象間的一種一對多的依賴關係,當一個對象的狀態發生改變時,全部依賴它的對象都將獲得通知。ide

@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更新。

相關文章
相關標籤/搜索