2021-01-29 Redux的源码简单实现

2021-01-29 Redux的源码简单实现

Reducer
reducer是什么,其实就是一个纯函数,接收旧的state和action,返回新的state

(preState,action)=>newState

之所以叫reducer,是和Array.prototype.reduce(reducer, initialValue)里的回调函数属于相同的类型。
保持reducer的纯净非常重要,永远不要再reducer里做以下操作:

  • 修改传入参数
  • 执行有副作用的操作,如API请求和路由跳转
  • 调用非纯函数,如Date.now()或Math.random等

compose
如果一个值要经过多个函数,才能变成另外一个值,就可以把所有中间步骤合并成一个函数,这叫函数的合成(compose)
合成的好处显而易见,它让代码变得更简单而且富有可读性,同时通过不同的组合方式,可以轻易组合出其他常用函数,让代码变得更具有表现力

/**
 * 组合函数
 */

function f1(arg) {
  console.log("f1", arg);
  return arg;
}

function f2(arg) {
  console.log("f2", arg);
  return arg;
}

function f3(arg) {
  console.log("f3", arg);
  return arg;
}

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

compose(f1,f2)("omg");
// console.log(compose(f1, f2, f3)("omg"));

Redux
Redux是Javascript应用的状态容器,是纯JS写的,保证程序行为一致性且易于测试
redux
redux应用举例:
1、需要一个store来存储数据
2、store里的reducer初始化state并定义state修改规则
3、通过dispatch一个action来提交对数据的修改
4、action提交到reducer函数里,根据传入的action的type,返回新的state

检查点:
1、createStore创建store
2、reducer初始化、修改状态函数
3、getState获取状态值
4、dispatch提交更新
5、subscribe变更订阅

手写redux相关API

应用容器store index.js

// import { createStore, applyMiddleware, combineReducers } from "redux";
import { createStore, applyMiddleware, combineReducers } from "./kredux";
// import thunk from "redux-thunk"; // 处理异步
// import logger from "redux-logger"; // 打印日志

function countReducer(state = 0, { type, payload }) {
  switch (type) {
    case "ADD":
      return state + payload;
    case "MINUS":
      return state - payload;
    default:
      return state;
  }
}

const store = createStore(
  // countReducer,
  combineReducers({ count: countReducer }), // 多个reducer处理
  applyMiddleware(thunk, logger)
);

export default store;

导出 kredux/index.js

import createStore from "./createStore";
import applyMiddleware from "./applyMiddleware";
import combineReducers from "./combineReducers";

export { createStore, applyMiddleware, combineReducers };

createStore-API:创建store

export default function createStore(reducer, enhancer) {
  // 如果存在中间件则执行以下
  if(enhancer){
    return enhancer(createStore)(reducer);
  }


  let currentState; // 初始为null 默认值没有作用(state为undefined走default,内部采用严格相等模式)
  let currentListeners = [];

  // get
  function getState() {
    return currentState;
  }

  // set
  function dispatch(action) {
    currentState = reducer(currentState, action);
    // state改变,执行订阅的函数
    currentListeners.forEach(listener => listener());
  }

  // 订阅和取消订阅要成对出现
  function subscribe(listener) {
    currentListeners.push(listener);
    return () => {
      const index = currentListeners.indexOf(listener);
      currentListeners.splice(index, 1);
    };
  }

  // 初始化的时候执行下dispatch,设置初始值
  dispatch({ type: "REDUXXXXXXX" });

  return {
    getState,
    dispatch,
    subscribe
  };
}

applyMiddleware-组合中间件

export default function applyMiddleware(...middlewares) {
  return createStore => reducer => {
    const store = createStore(reducer); // 得到store

    // 普通版的dispatch
    let dispatch = store.dispatch;

    // todo 加强版的dispatch
    let midAPI = {
      getState: store.getState,
      dispatch: (action, ...args) => dispatch(action, ...args) // 每个中间件都有自己的作用域
    };

    // 执行中间件数组
    const middlewareChain = middlewares.map(middleware => middleware(midAPI));

    // 用compose组合函数按顺序执行,得到加强版的dispatch
    dispatch = compose(...middlewareChain)(store.dispatch);

    return { ...store, dispatch };
  };
}

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

combineReducers-组合多个reducers为单一reducer

export default function combineReducers(reducers) {
  return function combination(state = {}, action) {
    let nextState = {};
    let hasChanged = false; // 初始值
    for (let key in reducers) {
      const reducer = reducers[key];
      nextState[key] = reducer(state[key], action);
      hasChanged = hasChanged || nextState[key] !== state[key];
    }

    /**
     * 动态改变reducer
     * {a: 1, b:2}
     * {a: 1 }
     */
    hasChanged =
      hasChanged || Object.keys(nextState).length !== Object.keys(state).length;
    return hasChanged ? nextState : state;
  };
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值