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);
}

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

相关推荐
说码解字6 分钟前
Kotlin lazy 委托的底层实现原理
前端
爱分享的程序员44 分钟前
前端面试专栏-算法篇:18. 查找算法(二分查找、哈希查找)
前端·javascript·node.js
翻滚吧键盘1 小时前
vue 条件渲染(v-if v-else-if v-else v-show)
前端·javascript·vue.js
vim怎么退出1 小时前
万字长文带你了解微前端架构
前端·微服务·前端框架
你这个年龄怎么睡得着的1 小时前
为什么 JavaScript 中 'str' 不是对象,却能调用方法?
前端·javascript·面试
Java水解1 小时前
前端常用单位em/px/rem/vh/vm到底有什么区别?
前端
CAD老兵1 小时前
Vite 如何借助 esbuild 实现极速 Dev Server 体验,并支持无 source map 的源码调试
前端
南屿im1 小时前
JavaScript 手写实现防抖与节流:优化高频事件处理的利器
前端·javascript
Spider_Man1 小时前
从零开始构建React天气应用:API集成与UI设计全指南 🌤️
前端·react.js
浩浩测试一下1 小时前
渗透信息收集- Web应用漏洞与指纹信息收集以及情报收集
android·前端·安全·web安全·网络安全·安全架构