美文网首页
模仿redux源码实现

模仿redux源码实现

作者: key君 | 来源:发表于2019-11-05 17:04 被阅读0次

原理:
MyReduxPage:引入store,store.subscribe()订阅消息,store.dispatch()派发消息,store.getState()获取数据
counterReducer:传入state和action,返回新的state
kRedux.js:定义了createStore方法,传入了counterReducer和applyMiddleware(logger, thunk)。
createStore内部定义了以下函数:
getState() 返回当前值。
subscribe(listener) currentListeners数组保存传入的方法(listener就是传入的方法)
dispatch(action) 其实是调用了counterReducer,传入一个对象里面包含type值,根据类型返回新的state给currentState保存。遍历之前保存的currentListeners数组,执行监听的所有方法。
createStore方法内部主动调用一次dispatch,因为第一次传入没有定义的类型,所以state返回0
applyMiddleware()实现:applyMiddleware(logger, thunk)(createStore)(reducer),主要做的事情是,把counterReducer传给createStore重新创建没有enhancer的store,拿出store.getState和store.dispatch作为api对象,遍历[logger,thunk]数组,给里面的方法传入api对象,返回一个新的函数数组。compose封装了一次dispatch方法,当执行dispatch方法的时候,先执行thunk 再执行logger 再执行dispatch。
MyReduxStore.js: createStore创建store实例,定义logger和thunk函数。
当执行dispatch时 执行thunk(logger(dispatch))

src/pages/MyReduxPage.js

import React, { Component } from "react";
import store from "../store/MyReduxStore";

export default class MyReduxPage extends Component {
  componentDidMount() {
    store.subscribe(() => {
      this.forceUpdate();
      // this.setState({});
    });
  }
  asyAdd = () => {
    store.dispatch(dispatch => {
      setTimeout(() => {
        dispatch({ type: "add" });
      }, 1000);
    });
  };
  render() {
    // console.log("store", store);
    return (
      <div>
        <h1>MyReduxPage</h1>
        <p>{store.getState()}</p>
        <button onClick={() => store.dispatch({ type: "add" })}>add</button>
        <button onClick={() => store.dispatch({ type: "minus" })}>minus</button>
        <button onClick={this.asyAdd}>asyAdd</button>
      </div>
    );
  }
}


src/store/MyReduxStore.js

import { createStore, applyMiddleware } from "../kRedux";

import { counterReducer } from "./counterReducer";

const store = createStore(counterReducer, applyMiddleware(logger, thunk));

function logger() {
  return dispatch => action => {
    action.type && console.log(action.type + "执行啦!");
    return dispatch(action);
  };
}

function thunk({ getState }) {
  return dispatch => action => {
    if (typeof action === "function") {
      return action(dispatch, getState);
    } else {
      return dispatch(action);
    }
    //console.log(action.type + "执行啦!");
    //return dispatch(action);
  };
}

export default store;


src/kRedux.js

export function createStore(reducer, enhancer) {
  if (enhancer) {
    return enhancer(createStore)(reducer);
  }

  let currentState = undefined;
  let currentListeners = [];
  function getState() {
    return currentState;
  }

  function dispatch(action) {
    currentState = reducer(currentState, action);
    currentListeners.map(lis => lis());
    return action;
  }

  function subscribe(listener) {
    currentListeners.push(listener);
  }
  dispatch({ type: "IMMOCC/KKKREDUX" });
  return {
    getState,
    dispatch,
    subscribe,
  };
}

export function applyMiddleware(...middlewares) {
  return createStore => (...args) => {
    const store = createStore(...args);
    const midAPi = {
      getState: store.getState,
      dispatch: store.dispatch,
    };
    const middlewareChain = middlewares.map(mw => mw(midAPi));
    const dispatch = compose(...middlewareChain)(store.dispatch);
    return {
      ...store,
      dispatch,
    };
  };
}

function compose(...funcs) {
  const len = funcs.length;
  if (len === 0) {
    return arg => arg;
  } else if (len === 1) {
    return funcs[0];
  } else {
    return funcs.reduce((a, b) => (...args) => b(a(...args)));
  }
}

src/store/counterReducer.js

export function counterReducer(state = 0, action) {
  switch (action.type) {
    case "add":
      return state + 1;
    case "minus":
      return state - 1;
    default:
      return state;
  }
}

相关文章

网友评论

      本文标题:模仿redux源码实现

      本文链接:https://www.haomeiwen.com/subject/kspdbctx.html