阿里云主机折上折
  • 微信号
您当前的位置:网站首页 > 状态管理库(Redux/Vuex)中的设计模式

状态管理库(Redux/Vuex)中的设计模式

作者:陈川 阅读数:5222人阅读 分类: JavaScript

状态管理库如Redux和Vuex是现代前端开发中处理复杂应用状态的核心工具,它们通过特定的设计模式实现数据的集中管理和可预测性更新。这些库背后的设计思想与经典的设计模式紧密相关,理解这些模式能更高效地使用状态管理工具。

单例模式与全局状态管理

Redux和Vuex的核心设计都采用了单例模式,确保整个应用只有一个全局状态树。这种设计避免了状态分散导致的同步问题,同时提供了统一的状态访问入口。

// Redux中的store单例实现
import { createStore } from 'redux';

const initialState = { count: 0 };

function reducer(state = initialState, action) {
  switch (action.type) {
    case 'INCREMENT':
      return { ...state, count: state.count + 1 };
    default:
      return state;
  }
}

const store = createStore(reducer); // 全局唯一store实例

Vuex的实现类似:

// Vuex中的store单例
import { createStore } from 'vuex';

const store = createStore({
  state() {
    return { count: 0 };
  },
  mutations: {
    increment(state) {
      state.count++;
    }
  }
});

观察者模式与状态订阅

状态管理库使用观察者模式实现组件与状态的自动同步。当状态变化时,所有订阅该状态的组件都会收到通知并更新。

Redux的订阅机制:

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

// 触发状态变化
store.dispatch({ type: 'INCREMENT' });

// 取消订阅
unsubscribe();

Vuex通过Vue的响应式系统自动处理依赖追踪:

<template>
  <div>{{ $store.state.count }}</div>
</template>

<script>
export default {
  mounted() {
    // 自动建立依赖关系
    console.log(this.$store.state.count);
  }
}
</script>

命令模式与Action/Commit

状态变更通过明确的命令(Action/Mutation)进行,这体现了命令模式的思想。将状态修改封装为离散的命令,使变更可追踪和可回放。

Redux中的action:

// Action创建函数
function increment() {
  return { type: 'INCREMENT' };
}

// 触发action
store.dispatch(increment());

// 带参数的action
function addTodo(text) {
  return { type: 'ADD_TODO', payload: { text } };
}

Vuex中的mutation:

const store = createStore({
  mutations: {
    addTodo(state, payload) {
      state.todos.push(payload.text);
    }
  }
});

// 提交mutation
store.commit('addTodo', { text: 'Learn Vuex' });

装饰器模式与中间件

Redux中间件系统是装饰器模式的典型应用,可以在不修改核心逻辑的情况下增强dispatch功能。

// 自定义logger中间件
const logger = store => next => action => {
  console.log('dispatching', action);
  let result = next(action);
  console.log('next state', store.getState());
  return result;
};

// 应用中间件
const store = createStore(
  reducer,
  applyMiddleware(logger)
);

Vuex也有类似的插件机制:

const myPlugin = store => {
  store.subscribe((mutation, state) => {
    console.log(mutation.type, mutation.payload);
  });
};

const store = createStore({
  // ...
  plugins: [myPlugin]
});

策略模式与Reducer设计

Redux的reducer函数体现了策略模式,通过不同的action类型选择不同的状态处理策略。

function todosReducer(state = [], action) {
  switch (action.type) {
    case 'ADD_TODO':
      return [...state, action.payload];
    case 'TOGGLE_TODO':
      return state.map(todo =>
        todo.id === action.payload.id
          ? { ...todo, completed: !todo.completed }
          : todo
      );
    default:
      return state;
  }
}

组合模式与模块化

大型应用的状态管理需要模块化组织,这体现了组合模式的思想。

Redux的combineReducers:

import { combineReducers } from 'redux';

const rootReducer = combineReducers({
  todos: todosReducer,
  visibilityFilter: visibilityFilterReducer
});

Vuex的模块系统:

const moduleA = {
  state: () => ({ ... }),
  mutations: { ... },
  actions: { ... }
}

const moduleB = {
  state: () => ({ ... }),
  mutations: { ... },
  actions: { ... }
}

const store = createStore({
  modules: {
    a: moduleA,
    b: moduleB
  }
})

备忘录模式与时间旅行调试

Redux DevTools实现的时间旅行功能基于备忘录模式,可以保存和恢复状态快照。

// 手动实现简单的时间旅行
const states = [];
let currentState = 0;

function saveState(state) {
  states.push(JSON.parse(JSON.stringify(state)));
  currentState = states.length - 1;
}

function undo() {
  if (currentState > 0) {
    currentState--;
    return states[currentState];
  }
  return null;
}

function redo() {
  if (currentState < states.length - 1) {
    currentState++;
    return states[currentState];
  }
  return null;
}

代理模式与Getter计算

Vuex的getters提供了派生状态的机制,这类似于代理模式,可以在访问状态时进行额外计算。

const store = createStore({
  state: {
    todos: [
      { id: 1, text: '...', done: true },
      { id: 2, text: '...', done: false }
    ]
  },
  getters: {
    doneTodos: state => {
      return state.todos.filter(todo => todo.done);
    },
    doneTodosCount: (state, getters) => {
      return getters.doneTodos.length;
    }
  }
});

// 访问getter
store.getters.doneTodos; // -> [{ id: 1, text: '...', done: true }]

工厂模式与Action创建

Redux中的action创建函数和Vuex中的action方法都体现了工厂模式,封装了action对象的创建过程。

// Redux action工厂函数
function makeActionCreator(type, ...argNames) {
  return function(...args) {
    const action = { type };
    argNames.forEach((arg, index) => {
      action[argNames[index]] = args[index];
    });
    return action;
  };
}

const ADD_TODO = 'ADD_TODO';
const addTodo = makeActionCreator(ADD_TODO, 'text', 'id');
console.log(addTodo('Learn Redux', 1));
// { type: 'ADD_TODO', text: 'Learn Redux', id: 1 }

Vuex中的异步action:

actions: {
  async fetchUser({ commit }, userId) {
    try {
      const user = await api.fetchUser(userId);
      commit('SET_USER', user);
    } catch (error) {
      commit('SET_ERROR', error);
    }
  }
}

状态模式与状态机

复杂的状态逻辑可以通过状态模式来管理,这在Redux和Vuex中都有体现。

// 订单状态机
const orderStateMachine = {
  pending: {
    confirm: 'confirmed',
    cancel: 'cancelled'
  },
  confirmed: {
    ship: 'shipped',
    cancel: 'cancelled'
  },
  shipped: {
    deliver: 'delivered'
  }
};

function orderReducer(state = { status: 'pending' }, action) {
  const nextStatus = orderStateMachine[state.status]?.[action.type];
  if (!nextStatus) return state;
  
  return { ...state, status: nextStatus };
}

依赖注入与Provider模式

React-Redux的Provider组件实现了依赖注入模式,将store注入到组件树中。

import { Provider } from 'react-redux';

ReactDOM.render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.getElementById('root')
);

// 组件中通过connect获取store
function connect(mapStateToProps) {
  return function(WrappedComponent) {
    return function(props) {
      const state = useReduxState();
      const stateProps = mapStateToProps(state);
      return <WrappedComponent {...props} {...stateProps} />;
    };
  };
}

本站部分内容来自互联网,一切版权均归源网站或源作者所有。

如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn

前端川

前端川,陈川的代码茶馆🍵,专治各种不服的Bug退散符💻,日常贩卖秃头警告级的开发心得🛠️,附赠一行代码笑十年的摸鱼宝典🐟,偶尔掉落咖啡杯里泡开的像素级浪漫☕。‌