React系列-Redux

redux/createStore方法返回getState、dispatch和subscribe。

  • 组件之间通过调用dispatch action,action传入到reducer中,然后根据老的state和action生成新的状态。监听渲染函数数组遍历执行
  • getState返回当前状态state
  • subscribe函数调用将渲染函数暂存到一个数组中,并返回一个函数用来过滤掉当前绑定函数,也就是取消订阅。
    function createStore(reducer){
        let state;
        getState = () => state;
        let listeners = [];
        let dispatch = function(action){
            state = reducer(state,action);
            listeners.forEach(fn=>fn())
        }
        <!--默认状态state-->
        dispatch({type:'@INIT'})
        let subscribe = function(fn){
            listeners.push(fn);
            return function(){
                listeners = listeners.filter(l=>l!=fn)
            }
        }
        return {
           getState,
           subscribe,
           dispatch
        }
    }
    
复制代码

reducer

reducer本身是一个函数,传递两个参数,分别为state和action,然后判断action.type来进行不同的逻辑来改变state

    import * as Types from '../action-types'
    function counter(state = {number:0},action){
      switch(action.type){
        case Types.INCREMENT:
          return {number:state.number+ action.count}
      }
      return state;
    }
    export default counter;
复制代码

redux/combineReducers

用来合并多个reducer

    function combineReducers(reducers){
        return function(state={},action){
            let obj = {};
            for (let key in reducers) {
                <!--第一次进来注意state[key]为undefined-->
                obj[key] = reducers[key](state[key], action);
            }
            return obj
        }
    }
    export default combineReducers({
      counter: counter,
      todo
    });
复制代码

action

action就是一个包括type和payload属性的对象

   export default {
      add(val){
        return {type:Types.INCREMENT,count:val}
      }
    } 
复制代码

bindActionCreators

将action包装成自动dispatch

    let bindActionCreators = (actions,dispatch) => {
      let obj = {}
      for(let key in actions){
        obj[key] = (...args) => dispatch(actions[key](...args))
      }
      return obj;
    }
复制代码

react-redux

用来连接react和redux的

Provider

    ReactDOM.render(<Provider store={store}>
    <>
      <Counter></Counter>
    </>
    </Provider>,window.root);
复制代码

Provider的实现(主要是使用context API)

    import React,{Component} from 'react';
    import Context from './context';
    // Provider 主要是提供store使用的
    export default class Provider extends Component{
       render(){
         return (<Context.Provider value={{ store: this.props.store}}>
             {this.props.children}
         </Context.Provider>)
     }
    }
复制代码

connect

第一次执行传递两个参数mapStateToProps和mapDispatchToProps,两个都是一个函数分别传递state和dispatch参数,返回对象。

    let mapStateToProps = (state) => { // store.getState()
       return {
        number: state.counter.number,
       }
     };
     let mapDispatchToProps = (dispatch) => { // store.dipspatch
       return {
        add: (n) => dispatch(actions.add(n))
      }
     }
    //如果connect 第一次执行的函数 ,如果第二个参数是对象类型 会自动内部调用bindActionCreator来实现 
    export default connect((state)=>state.counter,actions)(Counter)
复制代码

connect实现

context API + 高阶组件

    import React from 'react';
    import Context from './context';
    import { bindActionCreators} from 'redux'; 
    let connect = (mapStateToProps, mapDipsatchToProps)=> (Component)=>{
      return ()=>{
        class Proxy extends React.Component{
          state = mapStateToProps(this.props.store.getState());
          componentDidMount(){
            this.unsub = this.props.store.subscribe(()=>{
              this.setState(mapStateToProps(this.props.store.getState()))
            })
          }
          componentWillUnmount(){
            this.unsub();
          }
          render(){
            let mapDispatch;
            if (typeof mapDipsatchToProps === 'object'){ //如果第二个参数传递的是一个对象,把对象直接进行包装即可
              mapDispatch = bindActionCreators(mapDipsatchToProps,this.props.store.dispatch);
            }else{
              mapDispatch = mapDipsatchToProps(this.props.store.dispatch);
            }
            return <Component {...this.state} {...mapDispatch}></Component>
          }
        }
        return <Context.Consumer>
          {({store})=>{
            // 将状态 和dispatch 拿到执行函数 把结果对象传递给原本的component渲染
            return <Proxy store={store}></Proxy>
          }}
        </Context.Consumer>
      }
    }
    export default connect;


作者:折腾的小白攻城狮
链接:https://juejin.im/post/5c9ce73ae51d454cac6c6046
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

猜你喜欢

转载自blog.csdn.net/sinat_17775997/article/details/89442063
今日推荐