ByAI: Redux的typescript简化实现

Redux 是一个用于 JavaScript 应用的可预测状态容器,其核心原理基于 ​单向数据流 ​ 和 ​纯函数


一、Redux 核心原理

  1. 三大原则

    • 单一数据源:整个应用状态存储在一个全局 Store 中。
    • 状态只读 :只能通过 dispatch(action) 修改状态。
    • 纯函数更新 :通过 reducer 纯函数计算新状态。
  2. 关键角色

    • Store :保存状态,提供 dispatch/subscribe/getState 方法。
    • Action :描述变化的普通对象({ type: 'ACTION_TYPE', payload })。
    • Reducer :纯函数 (state, action) => newState

二、TypeScript 实现

1. 定义类型

typescript 复制代码
// Action 类型:基础 Action 必须包含 type 字段
type Action = {
  type: string;
  [key: string]: any; // 允许其他任意字段(如 payload)
};

// Reducer 类型:接收当前 state 和 action,返回新 state
type Reducer<S = any, A extends Action = Action> = (state: S, action: A) => S;

// Store 类型:包含核心方法
interface Store<S = any, A extends Action = Action> {
  getState(): S;
  dispatch(action: A): void;
  subscribe(listener: () => void): () => void; // 返回取消订阅函数
}

2. 创建 Store

typescript 复制代码
function createStore<S, A extends Action>(
  reducer: Reducer<S, A>,
  initialState: S
): Store<S, A> {
  let state = initialState;
  const listeners: Array<() => void> = [];

  // 获取当前状态
  const getState = (): S => state;

  // 分发 Action
  const dispatch = (action: A): void => {
    state = reducer(state, action); // 调用 reducer 计算新状态
    listeners.forEach(listener => listener()); // 通知所有订阅者
  };

  // 订阅状态变化
  const subscribe = (listener: () => void): () => void => {
    listeners.push(listener);
    // 返回取消订阅函数
    return () => {
      const index = listeners.indexOf(listener);
      if (index !== -1) listeners.splice(index, 1);
    };
  };

  // 初始化时触发一次 dispatch(可选,用于兼容某些中间件)
  dispatch({ type: '@@INIT' } as A);

  return { getState, dispatch, subscribe };
}

3. 组合多个 Reducer(combineReducers)

typescript 复制代码
function combineReducers<Reducers extends Record<string, Reducer>>(
  reducers: Reducers
): Reducer {
  return (state: any = {}, action: Action): any => {
    const newState: any = {};
    Object.keys(reducers).forEach(key => {
      newState[key] = reducers[key](state[key], action); // 分别调用子 reducer
    });
    return newState;
  };
}

三、完整使用示例

typescript 复制代码
// 1. 定义 State 和 Action 类型
interface CounterState {
  count: number;
}

type CounterAction = 
  | { type: 'INCREMENT' }
  | { type: 'DECREMENT' }
  | { type: 'SET_COUNT'; payload: number };

// 2. 实现 Reducer
const counterReducer: Reducer<CounterState, CounterAction> = (
  state = { count: 0 },
  action
) => {
  switch (action.type) {
    case 'INCREMENT':
      return { count: state.count + 1 };
    case 'DECREMENT':
      return { count: state.count - 1 };
    case 'SET_COUNT':
      return { count: action.payload };
    default:
      return state;
  }
};

// 3. 创建 Store
const store = createStore(counterReducer, { count: 0 });

// 4. 订阅状态变化
const unsubscribe = store.subscribe(() => {
  console.log('State changed:', store.getState());
});

// 5. 分发 Action
store.dispatch({ type: 'INCREMENT' }); // State: { count: 1 }
store.dispatch({ type: 'SET_COUNT', payload: 10 }); // State: { count: 10 }

// 6. 取消订阅
unsubscribe();

四、关键设计解析

  1. 不可变状态
    Reducer 必须返回新对象(如 { ...state, count: state.count + 1 }),而不是直接修改原 state。
  2. 时间旅行调试
    由于状态是纯函数计算的结果,可以轻松记录 action 和 state 的历史,实现时间旅行功能(如 Redux DevTools)。
  3. 中间件扩展
    实际 Redux 通过 applyMiddleware 增强 dispatch 功能(如异步处理),这里未实现,但原理是通过包装 dispatch 方法。
相关推荐
0思必得06 小时前
[Web自动化] Selenium处理动态网页
前端·爬虫·python·selenium·自动化
东东5166 小时前
智能社区管理系统的设计与实现ssm+vue
前端·javascript·vue.js·毕业设计·毕设
catino6 小时前
图片、文件的预览
前端·javascript
layman05288 小时前
webpack5 css-loader:从基础到原理
前端·css·webpack
半桔8 小时前
【前端小站】CSS 样式美学:从基础语法到界面精筑的实战宝典
前端·css·html
AI老李8 小时前
PostCSS完全指南:功能/配置/插件/SourceMap/AST/插件开发/自定义语法
前端·javascript·postcss
_OP_CHEN9 小时前
【前端开发之CSS】(一)初识 CSS:网页化妆术的终极指南,新手也能轻松拿捏页面美化!
前端·css·html·网页开发·样式表·界面美化
啊哈一半醒9 小时前
CSS 主流布局
前端·css·css布局·标准流 浮动 定位·flex grid 响应式布局
PHP武器库9 小时前
ULUI:不止于按钮和菜单,一个专注于“业务组件”的纯 CSS 框架
前端·css
电商API_180079052479 小时前
第三方淘宝商品详情 API 全维度调用指南:从技术对接到生产落地
java·大数据·前端·数据库·人工智能·网络爬虫