人人都会AI编程

State、Getters、Mutations、Actions、Modules

更新时间:2026-07-10

Vuex 是 Vue 2 时代官方提供的状态管理库,它采用单一状态树显式同步/异步分离的设计,将应用中的所有组件共享状态集中管理。尽管 Pinia 已经成为 Vue 3 的官方推荐方案,理解 Vuex 的核心概念仍然很有必要——很多存量项目仍在使用,而且 Pinia 本身就是对 Vuex 设计思想的演进和简化。


State:全局数据的唯一真相源

State 就是存储在 Vuex 中的一个响应式对象,整个应用仅有一个 Store 实例,所有组件都从这里读取数据。

// Vuex Store 定义
const store = createStore({
  state: {
    user: null,
    token: ''
  }
})

// 组件中通过计算属性读取
computed: {
  user() {
    return this.$store.state.user
  }
}
  • 确保数据唯一:与组件内部状态不同,State 里的数据可在任意组件中访问,避免了“各自维护一份副本”导致的同步问题。
  • 严格模式:Vuex 可以开启严格模式,在开发环境下,任何直接修改 State(非通过 Mutation)的行为都会报错,从机制上保证了数据流的可追溯性。

Getters:Store 的计算属性

Getters 用于从 State 中派生出新的状态,类似于 Vue 组件内的 computed。当多个组件需要同样的计算逻辑时,放在 Getters 中可以避免重复编码,并且自动缓存结果。

const store = createStore({
  state: {
    cart: [{ id: 1, price: 100, qty: 2 }]
  },
  getters: {
    cartTotal(state) {
      return state.cart.reduce((sum, item) => sum + item.price * item.qty, 0)
    }
  }
})

// 组件使用
computed: {
  total() {
    return this.$store.getters.cartTotal
  }
}

Mutations:唯一允许修改 State 的同步方法

Mutations 是 Vuex 中唯一能修改 State 的入口,且必须是同步函数。这种限制不是麻烦,而是一种数据流向的纪律:每一次状态变更都有明确的记录,方便调试和回放。

// 定义 Mutation
mutations: {
  SET_USER(state, payload) {
    state.user = payload
  }
}

// 组件中提交 Mutation
this.$store.commit('SET_USER', { name: 'Alice' })
  • 可追踪:Vue DevTools 会记录每一次 Mutation 的快照,你可以像操作 Git 一样检查状态的变更历史。
  • 约定纯同步:异步操作必须放在 Actions 中,保证 Mutation 的可预测性。

Actions:处理异步操作和业务逻辑

Actions 用来封装异步请求(如 API 调用)和包含多条 Mutation 的复合逻辑。它不直接修改 State,而是通过 commit 触发 Mutations 来完成状态更新。

actions: {
  async login({ commit }, credentials) {
    const user = await api.login(credentials)
    commit('SET_USER', user)
    return user
  }
}

// 组件中分发 Action
this.$store.dispatch('login', { email, password })
  • 可以在一个 Action 中提交多个 Mutation,执行完一步再下一步。
  • 支持 async/await,可以链式返回 Promise,方便组件在 Action 完成后执行后续操作(比如跳转页、弹窗提示)。

Modules:大型 Store 的模块化拆分

当应用庞大到 State、Mutations、Actions 都挤在一个对象里时,维护会变得困难。Modules 允许将 Store 拆分成多个子模块,每个模块拥有自己的 State、Getters、Mutations 和 Actions。

const moduleA = {
  state: () => ({ list: [] }),
  mutations: { ADD_ITEM(state, item) { state.list.push(item) } },
  actions: { ... },
  getters: { ... }
}

const store = createStore({
  modules: {
    a: moduleA
  }
})
  • 命名空间:默认模块的 State 是分离的,但 Getters、Mutations 和 Actions 会注册到全局。推荐使用 namespaced: true 开启模块命名空间,避免方法名冲突。
  • 动态注册:可以在运行时使用 store.registerModule 动态添加模块,适合按需加载的场景。

对比 Pinia:Vuex 的核心概念如何被简化

在 Pinia 中,这些概念被大幅精简:

  • 不再有 Mutations:Pinia 认为强制区分同步/异步增加了编码成本,因此允许在 Actions 中直接修改 State,也允许在组件中直接调用 store.xxx = value。开发体验更接近“直接改数据”,同时依然保持 DevTools 和时间旅行调试的支持。
  • 去除了 Modules 的嵌套树:每个 Store 天生就是一个模块,通过引入不同的 Store 文件实现逻辑拆分,不再需要冗长的模块注册,也不再需要记忆 rootState 和局部命名空间。
  • 完整的 TypeScript 支持:Pinia 从设计之初就以 TypeScript 为优先,类型推导非常完整,而 Vuex 在使用 TS 时往往需要繁重的类型声明。

一句话总结:Vuex 通过 State、Getters、Mutations、Actions、Modules 这五个概念,为大型应用构建了一条清晰、可管控的数据流向;而 Pinia 则在保留 Vuex 所有调试能力的基础上,去掉了 Mutations 和 Modules 的复杂性,让状态管理的代码更贴近“直接修改 JS 对象”的直觉体验。如果你是新项目,直接选择 Pinia 即可;如果仍在维护 Vuex 项目,理解这些概念就能轻松驾驭现有代码。