看不懂react-redux就写一个,超精简版

react-redux的代码,还挺多的,偷懒不想看,但是又怕别人问原理,所以就手撸一个来玩玩,超精简

惯例,先看react-redux的使用,这是一个按钮加一个p标签,初始化是0,点了以后随机生成数字,很简单,看不懂请看redux文档

index.jsx文件

import ReactDOM from "react-dom";
import React from "react";
import { createStore } from "redux";

import { Provider } from "react-redux";
import Comp1 from "./comp1.jsx";

class App extends React.Component {
  render() {
    return (
      
); } } // 定义一个reducer const reducer = (state = [], action) => { switch (action.type) { case "change_num": return { ...state, activeNum: action.activeNum }; default: return state; } }; // createStore const store = createStore(reducer, { activeNum: 0 }); ReactDOM.render( , document.getElementById("root") ); ================================================================= comp1.jsx文件 import React, { Component } from "react"; import { connect } from "react-redux"; // 定义action const action = val => ({ type: "change_num", activeNum: val }); class Comp1 extends Component { render() { const { activeNum, changeNum } = this.props; return (

{activeNum}

); } } const mapStateToProps = (state, ownProps) => ({ activeNum: state.activeNum }); const mapDispatchToProps = (dispatch, ownProps) => ({ changeNum: val => { dispatch(action(val)); } }); // 调用connect export default connect(mapStateToProps, mapDispatchToProps)(Comp1);

我们关注下react-redux做了什么事情,一个是connect,一个是Provider,没了。

我们都知道redux是发布订阅,那么react-redux就是要把这套发布订阅用起来,因为我们都看过react-redux了,知道他用了react的Context,那么毫无疑问store在Provider传入之后,是作为Context.Provider的value,不然让人家怎么发布和订阅呢,于是我们yy了一下Provider的代码

// 创建一个Context肯定是要的
const Context = React.createContext("hehe");

export class Provider extends React.Component {
  render() {
    return (
      // 不管怎样反正先把store给了value再说
      
        {this.props.children}
      
    );
  }
}

这样写我们至少把使用Provider的样子写出来了对吧,贴一下方便回忆

ReactDOM.render(
  
    
  ,
  document.getElementById("root")
);

然后就是connect了,我们看到它是一个高阶函数,传了两个mapxxx函数和组件,那么至少我们写的connect是个套了三层(两层?就这个意思)的函数,并且最里面一层返回了一个组件,这个组件订阅了store的变更,并且把store最新的值放到了被connect的Comp1上,我们yy一下这个组件的代码

import React from "react";

class Hoc extends React.Component {
  constructor(props) {
    super(props);
    // 这个state存在的意义就是下面订阅的时候触发更新,当然,是没有性能优化的,谁叫我们是超精简
    this.state = {};
  }

  componentDidMount() {
    // 这里我们订阅了store的变更,这个props上的属性是怎么来的我们马上就知道了
    this.props.store.subscribe(() => {
      // 这里不触发一下更新的话,store.getState()是不会变的
      this.setState({});
    });
  }

  render() {
    // 这里我们把两个mapxxx函数调用了一把,为什么这么调用,因为两个mapxxx函数就长了一副应该这么调用的脸
    const { comp: Comp, mapState, mapDispath, store } = this.props;
    const state = mapState(store.getState());
    const dispatch = mapDispath(store.dispatch);
    return ;
  }
}

上面的注释说得不太清楚,我们来看看两个mapxxx函数,mapStateToProps需要传入一个state对象,返回一个对象,里面是一些属性,让Comp1可以在props上拿到,mapDispatchToProps需要传入一个dispatch函数,返回一个对象,里面是一些函数,让Comp1可以调用,那么显然一个就是store的getState返回值,一个是store的dispatch方法了(应该还挺显然的吧?),不显然也没事,我们先这么写着

const mapStateToProps = (state, ownProps) => ({
  activeNum: state.activeNum
});

const mapDispatchToProps = (dispatch, ownProps) => ({
  changeNum: val => {
    dispatch(action(val));
  }
});

这样的话connect长啥样我们也推导出来了,就像这样

// 第一层,接收mapxxx
export function connect(mapState, mapDispath) {
  // 第二层,接收组件
  return function(comp) {
    // 终于到了Consumer的时候了
    return function() {
      return (
        
          {store => (
            
          )}
        
      );
    };
  };
}

好了,到这里,把上面写的这些代码片段合起来,创建一个文件叫做hello-redux.jsx,并把我们顶部例子里的react-redux替换掉,就可以跑了,大家可以试一试

当然,因为是精简版,所以问题很多,比如mapxxx里有个ownProps的参数我们就没给,那个叫hehe的Context在多个地方使用会不会有问题,之类的,但是我们不管了()

以上,谢谢。

你可能感兴趣的:(javascript)