大家好,我是小杨,一个在前端领域摸爬滚打了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
最后感谢各位的耐心观看,既然都到这了,点个 👍赞再走吧!