拆解Redux:从零手写一个状态管理器,彻底搞懂它的魔法!

大家好,我是小杨,一个在前端领域摸爬滚打了6年的"老油条"。今天想和大家聊聊Redux------这个曾经让我又爱又恨的状态管理库。很多新手觉得它复杂,但其实它的核心思想非常简单。为了彻底搞懂它,我决定带大家从零手写一个迷你Redux!

1. 为什么我需要Redux?一个血泪故事

还记得我刚接触复杂前端项目时,组件的状态传递像一团乱麻:

  • parentComponent 要传数据给 nestedChildComponent,得经过3层中间组件。
  • 兄弟组件之间修改状态?只能用回调地狱或者事件总线,代码难以维护。

直到我遇到了Redux,它的单一数据源单向数据流 像一束光拯救了我。但光会用不够,理解原理才能避免踩坑

2. Redux的三大核心:Store、Action、Reducer

先看官方定义?不,我用一个计数器例子解释:

javascript 复制代码
// 1. 定义Reducer(纯函数!)
function counterReducer(state = 0, action) {
  switch (action.type) {
    case 'INCREMENT':
      return state + 1;
    case 'DECREMENT':
      return state - 1;
    default:
      return state;
  }
}

// 2. 创建Store(Redux.createStore的秘密)
const store = myCreateStore(counterReducer);

// 3. 触发Action(为什么必须用dispatch?)
store.dispatch({ type: 'INCREMENT' });
console.log(store.getState()); // 输出:1

关键点:

  • Reducer必须是纯函数,不能直接修改state!
  • Action是一个普通对象,但必须有type字段。
  • Store通过dispatch管理状态变更,避免随意修改。

3. 手写myCreateStore:20行代码揭示核心原理

Redux的魔法就藏在createStore里!下面是我的实现:

javascript 复制代码
function myCreateStore(reducer) {
  let currentState;
  const listeners = [];

  function getState() {
    return currentState;
  }

  function dispatch(action) {
    currentState = reducer(currentState, action);
    listeners.forEach(listener => listener()); // 通知所有订阅者
  }

  function subscribe(listener) {
    listeners.push(listener);
    return () => {
      const index = listeners.indexOf(listener);
      listeners.splice(index, 1);
    };
  }

  dispatch({ type: '@@INIT' }); // 初始化state
  return { getState, dispatch, subscribe };
}

为什么这样设计?

  • listeners 数组实现观察者模式,状态变化时自动更新UI(比如React的connect)。
  • 初始dispatch确保Reducer返回默认state。

4. 实战踩坑:我曾经犯过的3个错误

❌ 直接修改state

javascript 复制代码
// 错误写法!
function wrongReducer(state = { count: 0 }, action) {
  state.count += 1; // 直接修改了原state!
  return state;
}

后果: React组件不会重新渲染,因为浅比较发现引用未变。

❌ 在Reducer里执行异步操作

javascript 复制代码
// 错误示例!
function asyncReducer(state, action) {
  fetch('/api').then(() => { // 副作用!
    return { ...state, data: action.payload };
  });
}

正确做法: 用中间件(如redux-thunk)处理异步。

❌ 滥用Store存储局部状态

教训: 表单的临时输入值应该用组件state,而非全局Store。

5. 进阶:中间件(Middleware)机制揭秘

Redux最强大的特性是中间件。比如实现一个logger:

javascript 复制代码
function loggerMiddleware(store) {
  return function(next) {
    return function(action) {
      console.log('dispatching:', action);
      const result = next(action);
      console.log('next state:', store.getState());
      return result;
    };
  };
}

洋葱模型: 中间件的嵌套执行流程是Redux的灵魂。

6. 总结:Redux的设计哲学

  • 单向数据流:状态变化可预测。
  • 函数式编程:Reducer是纯函数,易于测试。
  • 发布订阅:高效管理状态依赖。

我的建议: 即使现在用Redux Toolkit或Zustand,理解Redux原理依然能让你更好地驾驭状态管理。

⭐ 写在最后

请大家不吝赐教,在下方评论或者私信我,十分感谢🙏🙏🙏.

✅ 认为我某个部分的设计过于繁琐,有更加简单或者更高逼格的封装方式

✅ 认为我部分代码过于老旧,可以提供新的API或最新语法

✅ 对于文章中部分内容不理解

✅ 解答我文章中一些疑问

✅ 认为某些交互,功能需要优化,发现BUG

✅ 想要添加新功能,对于整体的设计,外观有更好的建议

✅ 一起探讨技术加qq交流群:906392632

最后感谢各位的耐心观看,既然都到这了,点个 👍赞再走吧!

相关推荐
芝士加3 分钟前
一个有趣的搜索神器:pinyin-match
前端·javascript·开源
得物技术10 分钟前
基于TinyMce富文本编辑器的客服自研知识库的技术探索和实践|得物技术
前端·aigc·openai
一只大黑洋11 分钟前
Clipboard.js 复制内容
前端·javascript·vue.js
前端灵派派11 分钟前
openlayer绘制图形
前端
moyu8412 分钟前
ES6 Set与Map完全指南:从入门到性能优化
前端
然我14 分钟前
从 “只会聊天” 到 “能办实事”:OpenAI Function Call 彻底重构 AI 交互逻辑(附完整接入指南)
前端·javascript·人工智能
艾小码15 分钟前
深入解析CSS伪类:从基础到高级实战指南
前端·css
鹏多多15 分钟前
vue混入mixins详解和生命周期影响
前端·javascript·vue.js
汪子熙16 分钟前
HTML 中的 Bidirectional Isolate (bdi) 元素深入解析
前端·javascript