Vuex 使用详解
Vuex 是 Vue.js 的官方状态管理库,专为 Vue.js 应用程序开发的状态管理模式。下面我将全面介绍 Vuex 的核心概念、使用方法和最佳实践。
一、Vuex 核心概念
1. Vuex 架构图
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ Actions │───>│ Mutations │───>│ State │
└─────────────┘ └─────────────┘ └─────────────┘
▲ │
└─────────────────────────────────────┘
2. 五大核心概念
- State:应用状态数据源
- Getters:从 state 派生的计算属性
- Mutations:修改 state 的唯一途径(同步)
- Actions:提交 mutation,可包含异步操作
- Modules:将 store 分割成模块
二、基本使用
1. 安装与引入
npm install vuex --save
// store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
count: 0
},
mutations: {
increment (state) {
state.count++
}
},
actions: {
incrementAsync ({ commit }) {
setTimeout(() => {
commit('increment')
}, 1000)
}
},
getters: {
doubleCount: state => state.count * 2
}
})
// main.js
import store from './store'
new Vue({
store,
// ...其他配置
}).$mount('#app')
2. 在组件中使用
// 访问 state
this.$store.state.count
// 调用 mutation
this.$store.commit('increment')
// 调用 action
this.$store.dispatch('incrementAsync')
// 访问 getter
this.$store.getters.doubleCount
三、核心概念详解
1. State
定义:存储应用状态的单一数据源
state: {
user: {
name: 'John',
age: 30
},
todos: []
}
组件中访问:
// 直接访问
this.$store.state.user.name
// 使用 mapState 辅助函数
import { mapState } from 'vuex'
computed: {
...mapState(['user']),
...mapState({
userName: state => state.user.name
})
}
2. Getters
定义:基于 state 的计算属性
getters: {
completedTodos: state => {
return state.todos.filter(todo => todo.completed)
},
completedTodosCount: (state, getters) => {
return getters.completedTodos.length
}
}
组件中访问:
// 直接访问
this.$store.getters.completedTodos
// 使用 mapGetters 辅助函数
import { mapGetters } from 'vuex'
computed: {
...mapGetters(['completedTodos']),
...mapGetters({
doneTodos: 'completedTodos'
})
}
3. Mutations
定义:修改 state 的唯一方法(同步)
mutations: {
increment (state, payload) {
state.count += payload.amount
}
}
组件中提交:
// 直接提交
this.$store.commit('increment', { amount: 10 })
// 对象风格提交
this.$store.commit({
type: 'increment',
amount: 10
})
// 使用 mapMutations 辅助函数
import { mapMutations } from 'vuex'
methods: {
...mapMutations(['increment']),
...mapMutations({
add: 'increment'
})
}
4. Actions
定义:提交 mutation,可包含异步操作
actions: {
async fetchUser ({ commit }, userId) {
try {
const user = await api.getUser(userId)
commit('setUser', user)
} catch (error) {
commit('setError', error)
}
}
}
组件中分发:
// 直接分发
this.$store.dispatch('fetchUser', { userId: 123 })
// 对象风格分发
this.$store.dispatch({
type: 'fetchUser',
userId: 123
})
// 使用 mapActions 辅助函数
import { mapActions } from 'vuex'
methods: {
...mapActions(['fetchUser']),
...mapActions({
getUser: 'fetchUser'
})
}
5. Modules
定义:将 store 分割成模块
const moduleA = {
state: () => ({ ... }),
mutations: { ... },
actions: { ... },
getters: { ... }
}
const moduleB = {
state: () => ({ ... }),
mutations: { ... },
actions: { ... }
}
const store = new Vuex.Store({
modules: {
a: moduleA,
b: moduleB
}
})
命名空间:
const moduleA = {
namespaced: true,
state: () => ({ ... }),
// ...
}
// 访问命名空间模块
this.$store.state.a // -> moduleA 的状态
this.$store.getters['a/someGetter']
this.$store.commit('a/someMutation')
this.$store.dispatch('a/someAction')
// 辅助函数中使用命名空间
...mapActions('a', ['someAction'])
四、高级用法
1. 插件开发
const myPlugin = store => {
// 初始化时调用
store.subscribe((mutation, state) => {
// 每次 mutation 之后调用
console.log(mutation.type)
})
}
const store = new Vuex.Store({
// ...
plugins: [myPlugin]
})
2. 严格模式
const store = new Vuex.Store({
// ...
strict: process.env.NODE_ENV !== 'production'
})
3. 表单处理
// 使用计算属性的 getter/setter
computed: {
message: {
get () {
return this.$store.state.obj.message
},
set (value) {
this.$store.commit('updateMessage', value)
}
}
}
五、最佳实践
-
项目结构组织:
store/ ├── index.js # 组装模块并导出 store ├── actions.js # 根级别的 actions ├── mutations.js # 根级别的 mutations ├── modules/ │ ├── cart.js # 购物车模块 │ └── products.js # 产品模块 -
遵循规则:
- 应用层级的状态应该集中到 store 中
- 提交 mutation 是更改状态的唯一方法
- 异步逻辑应该封装在 action 里面
-
模块化开发:
- 大型应用应该分割 store 为多个模块
- 为业务相关的模块启用命名空间
-
TypeScript 支持:
// store/types.ts export interface State { count: number } // store/index.ts import { InjectionKey } from 'vue' import { createStore, Store } from 'vuex' export const key: InjectionKey<Store<State>> = Symbol() export const store = createStore<State>({ state: { count: 0 } })
六、Vuex 与 Composition API
在 Vue 3 中使用 Vuex:
import { useStore } from 'vuex'
export default {
setup() {
const store = useStore()
const count = computed(() => store.state.count)
function increment() {
store.commit('increment')
}
return {
count,
increment
}
}
}
七、Vuex 替代方案
-
Pinia(Vue 3 推荐):
- 更简单的 API
- 更好的 TypeScript 支持
- 组合式 API 友好
-
Composition API 的 reactive:
- 小型应用可以使用 provide/inject + reactive
- 适合简单状态管理需求
八、总结
Vuex 提供了集中式的状态管理方案:
-
核心流程:
- 组件 Dispatch → Actions → Commit → Mutations → Mutate State → Render
-
使用原则:
- 单一状态树
- 状态响应式
- 只能通过 mutation 修改状态
-
适用场景:
- 中大型单页应用
- 多个组件共享状态
- 需要跟踪状态变化
-
学习路径:
- 掌握基本概念(State, Getters, Mutations, Actions)
- 理解模块化组织
- 熟悉辅助函数使用
- 了解插件开发和严格模式
对于新项目,特别是 Vue 3 项目,可以考虑使用 Pinia 作为更现代的替代方案,但理解 Vuex 的核心概念对于维护现有项目和学习状态管理原理仍然非常重要。