实现一个自己的react-redux

本文深入解析Redux作为前端状态管理工具的核心价值,介绍了其架构模式及如何与React集成,同时提供了简单的编码实现示例。

Redux

相关概念

Redux是一种新型的前端“架构模式”。经常和 React.js 一并提出,如果要使用 React.js 基本都要伴随着 Redux 和 React.js 结合的库 React-redux。

要注意的是,Redux 和 React-redux 并不是同一个东西。Redux 是一种架构模式(Flux 架构的一种变种),它不关注你到底用什么库,你可以把它应用到 React 和 Vue,甚至跟 jQuery 结合都没有问题。而 React-redux 就是把 Redux 这种架构模式和 React.js 结合起来的一个库,就是 Redux 架构在 React.js 中的体现

可以这么理解,Redux就是一个用于共享状态管理的工具,就是一个保存了许多数据的js。既然说到共享状态管理,在不引入Redux时,我们通常会这么做:
1. 共享状态不就是指有一些状态需要被的多个组件所共用吗?并且这个状态还会需要被改变。那我们直接把这个状态放在这些下级组件所共有的祖先组件就行了,然后通过将改变状态的函数通过props传递给下级组件就行了。如果层级不深的话,这样做是可行的。但是往往我们的组件层级都会达到3、4层甚至更多。这个时候通过props方式来调用或者改变状态就会变得非常繁杂。

  1. 可以使用上下文,但是官方不推荐。原因大概是使用context修改共享状态太容易了,基本无门槛。修改了状态很难追溯到源头,导致维护和调试变得复杂“。
    所以对于Redux的作用可以归纳为:
  2. 不容易的修改共享状态
  3. 有门槛的修改共享状态
  4. 高调(大张旗鼓的调用修改reducer)的修改共享状态
  5. 使修改状态容易被追溯

在实现Redux之前,先了解几个跟Redux相关的概念:
1. Provider
2. createStore
3. connect
4. store(subscriber、getState、dispatch)
上述概念各自的作用:
1. Provider:用于提共享状态的一个纯组件而已
2. createStore: 用于创建store即包含了共享状态和dispatch的对象
3. connect: 用于将普通组件改造成能接收并且修改共享状态的一个纯函数
4. store: 只是一个名字真正重要的是括号中的东西。subscriber:订阅者模式中的订阅者,用于添加回调函数。getState:对外公共方法,用于提供共享状态。dispatch:用于修改共享状态。

编码实现

创建redux.jsreact-redux.js
编辑redux.js

/**
* 用于创建store
* @param reducer 用户自己创建的reducer
*/
function createStore(reducer) {
    var state = null;
    var listeners = [];
    //dispatch用于派发事件,action包含type和用户自定义的状态信息
    var dispatch = function(action) {
        //更新共享状态
        state = reducer(state,action);
        //派发监听事件
        listeners.forEach(function(listener) {
            listener();
        });
    };
    //订阅者模式,用于实现共享状态更新后,通知React进行更新
    var subscriber = function(listener) {
        listeners.push(listener);
    };
    //用于提供state
    var getState = function() {
        return state;
    };
    //首次调用,用于初始化共享状态的值
    dispatch();
    return {
        dispatch: dispatch,
        subscriber: subscriber,
        getState: getState
    };
}
export default createStore;

react-redux.js:

import React,{Component} from 'react';
import PropTypes from 'prop-types';

/**
* Provider只是一个用于提供上下文的组件
*/
export class Provider extends Component {

    static childContextTypes = {
        store: PropTypes.object
    }

    getChildContext() {
        return {
            store: this.props.store
        }
    }

    render() {
        return (
            <div>{this.props.children}</div>
        )
    }
}
/**
* connect接收用户自定义的mapStateToProps,mapDispatchToProps
* mapStateToProps,mapDispatchToProps用于将state及dispatch以用户自定义的方式提供。
*/
export var connect = function(mapStateToProps,mapDispatchToProps) {
    return function(WrapperComponent) {
        class ConnectComponent extends Component {

            static contextTypes = {
                store: PropTypes.object
            }

            constructor(props) {
                super(props);
                this.state = {
                    allProps: {}
                }
            }

            componentWillMount() {
                //添加监听函数,用于在共享状态改变之后调用以使组件更新
                this.context.store.subscriber(()=>this.updateProps());
                //初始调用,以使组件获取共享状态的初始值
                this.updateProps();
            }

            updateProps() {
                var store = this.context.store;
                //通过mapStateToProps,mapDispatchToProps来分发共享状态
                var stateProps = mapStateToProps?mapStateToProps(store.getState()):{};
                var dispatchProps = mapDispatchToProps?mapDispatchToProps(store.dispatch):{};
                this.setState({
                    allProps: {
                        ...this.props,
                        ...stateProps,
                        ...dispatchProps
                    }
                });
            }

            render() {
                //将用户需要的共享状态和上级传入的属性、修改状态的事件以props的形式传递
                return (<WrapperComponent {...this.state.allProps}/>)
            }
        }
        return ConnectComponent;
    }
}

接下来可以像使用react-redux一样使用它们,但是并不完全包含官方Redux所具备的功能。实际上redux和react-redux的实现比这个要复杂的多,例如可以使用中间件等。

参考文档:
http://huziketang.com/books/react/lesson30

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值