let us say say Redux和它的中间件机制

Redux

首先一张图看看Redux基本内容:

react-redux

还是一张图看看如何在React中使用Redux:

中间件

这就不是一张图可以解释的了。

什么是中间件

允许开发者在派发一个action到他最终被reducer处理之前,对action进行一些额外的处理。

主要是增强store.dispatch的能力。

如何自定义中间件

重写dispatch方法

类似于VUE中数组实现响应式的原理:

js 复制代码
import { combineReducers,createStore } from 'redux';
import countReducer from "./reducers/count";
import userReducer from "./reducers/user";

const rootReducer = combineReducers({
  count:countReducer,
  user:userReducer
});

const store = createStore(rootReducer);

// 通过重写dispatch实现响应式
const originDispatch= store.dispatch; //缓存原始dispatch
store.dispatch = function(action){
  // 执行中间操作
  console.log('中间件获取action',action);
  console.log('中间件获取state',store.getState());
  originDispatch(action); //调用原始dispatch
};

export default store;

官方推荐方法

自定义 Redux 中间件通常涉及编写一个函数,该函数接收 store 对象的 dispatchgetState 方法,并返回一个函数,该函数再次接收 nextaction,允许你在 action 到达 reducer 之前或之后执行一些逻辑。

js 复制代码
const loggerStateMiddleware = store => next => action => {
  console.log('自定义middleWare2-logger-state', store.getState());
  return next(action);
};

export default loggerStateMiddleware;


const store = createStore(rootReducer,applyMiddleware(loggerStateMiddleware));

中间件的原理

首先从使用中间件的语法入手:

js 复制代码
const store = createStore(
  rootReducer,
  applyMiddleware(middleware1, middleware2)
);

那么接下来看看createStore做了什么呢?简化版createStore如下:

js 复制代码
function createStore(reducer, preloadedState, enhancer) {

/**createStore接收三个参数
 * 第一个参数是 rootReducer,用于处理状态变化,
 * 第二个参数是可选的初始状态(preloadedState),
 * 第三个参数是中间件链enhancer。
 */
 
  // 如果传入了 enhancer,则使用 enhancer 增强 createStore
  if (typeof enhancer === 'function') {
    return enhancer(createStore)(reducer, preloadedState);
  }

  // 内部状态
  let currentState = preloadedState;
  let currentReducer = reducer;
  let listeners = [];

  // 获取当前状态
  function getState() {
    return currentState;
  }

  // 触发 action,并更新状态
  function dispatch(action) {
    currentState = currentReducer(currentState, action);

    // 通知所有监听器(订阅者)
    listeners.forEach(listener => listener());

    return action;
  }

  // 订阅状态变化
  function subscribe(listener) {
    listeners.push(listener);

    // 返回一个取消订阅的函数
    return function unsubscribe() {
      listeners = listeners.filter(l => l !== listener);
    };
  }

  // 初始化 store
  dispatch({ type: '@@redux/INIT' });

  // 返回 store 对象
  return {
    getState,
    dispatch,
    subscribe,
  };
}

知道了createStore的基本处理,接下来看看applyMiddleware做了什么:

由下可以看出:

  • applyMiddleware内部也重写了dispatch
js 复制代码
function applyMiddleware(...middlewares) {
  // 返回一个高阶函数,接收 createStore 作为参数
  return createStore => reducer => {
    // 创建原始的 Redux store
    const store = createStore(reducer);
    
    // 初始化 dispatch 函数,指向原始的 store.dispatch
    let dispatch = store.dispatch;

    // middlewareAPI 包含 getState 和 dispatch 方法
    const middlewareAPI = {
      getState: store.getState,
      dispatch: action => dispatch(action)
    };

    // 将每个中间件传入 middlewareAPI,得到包装后的中间件函数
    const chain = middlewares.map(middleware => middleware(middlewareAPI));

    // compose 函数用于将多个函数从右到左组合起来
    dispatch = compose(...chain)(store.dispatch);

    // 返回一个增强版的 store,其中的 dispatch 已经被中间件包装
    return {
      ...store,
      dispatch
    };
  };
}

// compose 函数用于将多个函数组合成一个函数
function compose(...funcs) {
  return arg => funcs.reduceRight((composed, f) => f(composed), arg);
}

接下来一张图就能说清整体的流程了:

相关推荐
齐 飞10 分钟前
MongoDB笔记02-MongoDB基本常用命令
前端·数据库·笔记·后端·mongodb
巧克力小猫猿26 分钟前
基于ant组件库挑选框组件-封装滚动刷新的分页挑选框
前端·javascript·vue.js
FinGet35 分钟前
那总结下来,react就是落后了
前端·react.js
前端李易安35 分钟前
手写一个axios方法
前端·vue.js·axios
XinZong1 小时前
【VSCode插件推荐】想准时下班,你需要codemoss的帮助,分享AI写代码的愉快体验,附详细安装教程
前端·程序员
trim1 小时前
写了个可以在工作中快速摄取知识的神器,都来体验体验
前端·产品
ErvinHowell1 小时前
文件MD5生成性能大提升!如何实现分片与Worker优化
前端·vue.js·算法
想做白天梦1 小时前
LeetCode :150. 逆波兰表达式求值(含求后缀表达式和中缀转后缀表达式)
java·前端·算法
s甜甜的学习之旅2 小时前
前端js处理list(数组)
开发语言·前端·javascript
小布布的不2 小时前
MyBatis 返回 Map 或 List<Map>时,时间类型数据,默认为LocalDateTime,响应给前端默认含有‘T‘字符
前端·mybatis·springboot