React 中redux和react-redux的实现

实现redux中的方法

/*
* createStore 创建REDUX容器
*   @PARAMS
*   reducer:函数
*   @RETURN
*   store:{
*     getState,
*     dispatch,
*     subscribe
*   }
* */
function createStore(reducer) {
//  创建一个store,STATE用来存储管理的状态信息,LISTENARY用来存储事件池中的方法
//  state不用设置初始值,因为dispatch执行REDUCER,STATE没有值,走的是REDUCER中赋值
//  的默认信息,我们自己创建容器的时候就把DISPATCH执行一次
  let state, listenAry = [];

  //  基于dispatch实现任务派发
  function dispatch(action) {
    //    执行reducer,修改容器中的状态信息(接收REDUCER的返回值,把返回的信息替换原有的STATE),
    //    值得注意的是:我们是把返回值全部替换成STATE,所有要求REDUCER中修改状态之前,要先把
    //    原始状态的信息克隆一份,在进行单个的属性修改
    state = reducer(state, action);
    //     2.通知事件池中方法执行
    for (let i = 0; i < listenAry.length; i++) {
      let item = listenAry[i];
      if (typeof item === 'function') {
        item();
      } else {
        listenAry.splice(i, 1);
        i--;//此处的作用是防止数组塌陷
      }
    }
  }

  dispatch({ type: '_INIT_DEFAULT_STATE' });//=>容器创建的时候执行一次DISPATCH,目的是把REDUCER中的默认状态信息赋
  // 值给redux容器中的状态

  //=>GET-STATE :获取容器中的状态信息
  function getState() {
//      我们需要保证返回的状态信息不能和容器中的STATE是同一个堆内存(否则外面获取
//      状态信息后,直接就可以修改容器中的状态了,这不符合DISPATCH->REDUCER才能改状
//      态的规范)
    return JSON.parse(JSON.stringify(state));//深度克隆
  }

//    =>SUBSCRIBE:向事件池中追加方法
  function subscribe(fn) {
// 向容器中追加方法(去重验证)
    let isExit = listenAry.includes(fn);
    !isExit ? listenAry.push(fn) : null;
//  2返回一个方法:执行返回的方法会把当前绑定的方法在事件池中移除掉
    return function unsubscribe() {
      let index = listenAry.indexOf(fn);
      listenAry.splice(index, 1);//数组中直接删除前面数组的方法会引起数组塌陷
    };
  }

  return {
    dispatch,
    getState,
    subscribe,
  };
}

//let reducer = (state, action) => {
  =>state 原有状态信息
  =>ACTION: 派发任务时传递的行为对象
//  switch (action.type) {
//    //根据不同的TYPE执行不同的STATE修改操作
//    case TYPE.XXX:
//      state = { ...state, n: 5 };
//  }
//  return state;//返回的state会替换原有的state
//};
//let store = createStore(reducer);
//=>CREATE的时候把REDYCER传递进来,但此时REDUCER比没有执行呢,
// 只有DISPATCH时候才执行,通过执行REDUCER修改容中的状态
//store.dispatch({type:"xxx",...})

//let unsubscribe = store.subscribe(fn);
//unsubscribe(); 移除追加的方法

/*
* combineReducers:REDUCER 合并的方法
*   @PARAMS
*     对象,对象中包含了每一个版块对象的REDUCER=>{xxx:function reducer...}
*   @RETURN
*     返回的是一个新的REDUCER函数(把这个值赋值给CREATE-STORE)
*  特殊处理:合并REDUCER之后,REDUX容器中的STATE也变为以对应对象管理的模式=>{xxx:{}...}
* */

function combineReducers(reducers) {
//=>REDUCERS:传递劲来的REDUCER对象集合
  /*
  * {
  *   vote:function reducer(state={n:0,m:0}){ ... return state}
  *   person:function reducer(state={baseInfo:""}){ ... return state}
  * }
  * */
  return function reducer(state = {}, action) {
    //=>DISPATCH派发执行的时候,执行的是返回的REDUCER,这里也要返回一个最终的STATE对象
    // =>替换原有的STATE,而且这个STATE中包含每个模块的状态信息=>{vote:...,person:...}
    // =>我们所谓的REDUCER合并,其实就是DISPATCH派发的时候,把每个模块的REDUCER都单独执行一遍
    //    把每个模块返回的状态最后在汇总在一起,替换容器中的状态信息
    let newState = {};
    for (let key in reducers) {
      if (!reducers.hasOwnProperty(key)) break;
      //reducers[key];每个模块单独的reducer
      //state[key]当前模块在REDUX容器中存储的状态信息
      //=>返回值是当前模块最新的状态,把它放到NEW-STATE中
      newState[key] = reducers[key](state[key], action);
    }
    return newState;
  };
}

store = createStore(reducer);
store.dispatch({ type: 'xxx' });


react-redux中的方法Provider和connect高阶组件的实现

import React from 'react';
import PropTypes from 'prop-types';

/*
* PROVIDER:当前项目的根组件
*   1.接收通过属性传递进来的STORE,把STORE挂载到上下文中,这样当前项目中任何一个组件中,想要
*   使用REDUX中的STORE,直接通过上下文即可
*   2.在组件的RENDER中,把传递给PROVIDER的子元素渲染
* */
class Provider extends React.Component {
  //设置上下文信息类型
  static childContextTypes = {
    store: PropTypes.object,
  };

  //设置上下文信息值
  getChildContext() {
    return {
      store: this.props.store,
    };
  }

  constructor(props, context) {
    super(props, context);
  }

  render() {
    return this.props.children;
  }

}

/*
*CONNECT:高阶组件(基于高阶函数:函数柯理化) 创建的组件就是高阶组件
*   @PARAMS
*     mapStateToProps:回调函数,把REDUX中的部分状态信息挂载到指定组建的属性上
*       ```
*       `mapStateToProps(state){
*           state:REDUX容器中的状态信息
*           return{};//=>RETURN对象中有啥,就把啥挂载带属性上
*       }
*       ```
*       mapDispatchToProps:回调函数,把一些需要派发的任务方法也挂载到组件的属性上
*       ```
*        function mapDispatchToProps(dispatch){
*           return {}//=>RETURN 啥就把啥挂载到属性上(返回的方法中有执行dispatch派发任务的操作)
*        }
*       ```
*    @RETURN
*       返回一个新的函数
*    =======
*    connectHOT
*       @PARAMS
*           传递进来的是要操作的组件,我们需要把指定的属性和方法都挂载到当前属性的
*           组件上
*       @RETURN
*           返回一个新的组件Proxy(代理组件),在代理组件中,我们要获取Provider在上下文
*           中存储的store,紧接着获取store中的state和dispatch,把mapStateToProps,mapDispatchToProps
*           回调函数执行,接收返回的结果,在把这些结果挂载到Component这个要操作的组件的属性上

* */
function connect(mapStateToProps, mapDispatchToProps) {
  return function connectHOT(Component) {
    return class Proxy extends React.Component {
//      =>获取上下文中的STORE
      static contextTypes = {
        store: PropTypes.object,
      };

//      =>获取STORE中的STATE/DISPATCH ,把传递的俩个回调函数执行,接收返回的结果
      constructor(props, context) {
        super(props, context);
        this.state = this.queryMountProps();
      }

//=>基于REDUX中的SUBSCRIBE向事件池中追加一个方法,当容器中状态改变,我们需要重新获取
//      最新的状态信息,并且重新把COMPONENT渲染,把最新的状态信息通过属性传递给COMPONENT
      componentDidMount() {
        this.context.store.subscribe(() => {
          this.setState(this.queryMountProps());
        });
      }

//      =>渲染COMPONENT组件,并且把获取的信息(状态,方法)挂载到组件属性上(单独调取
//      POXY组件的是时候传递给Component)
      render() {
        return <Component {...this.state} {...this.props}/>;
      }

//      =>从redux中获取最新的信息,基于回调函数筛选,返回的是需要挂载到组件属性上的信息
      queryMountProps = () => {
        let { store } = this.context,
          state = store.getState();
        let propsState = typeof mapStateToProps === 'function'
          ? mapStateToProps(state)
          : {};
        let propsDispatch = typeof mapDispatchToProps === 'function'
          ? mapDispatchToProps(store.dispatch)
          : {};
        return { ...propsState, ...propsDispatch };
      };
    };
  };
}

export { Provider };

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值