redux原理分析
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更新。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |