Vuex状态管理
外观
Vuex 是 Vue.js 的官方状态管理库,用于集中式存储和管理应用的所有组件的状态。它采用单向数据流模式,确保状态变更可预测且易于调试,特别适合中大型单页应用(SPA)。
核心概念[编辑 | 编辑源代码]
状态(State)[编辑 | 编辑源代码]
Vuex 使用单一状态树(Single State Tree)存储整个应用的状态,相当于组件的 "data" 但全局共享。
const store = new Vuex.Store({
state: {
count: 0,
user: { name: 'Alice' }
}
})
获取状态[编辑 | 编辑源代码]
组件通过 this.$store.state
或 mapState
辅助函数访问状态:
// 选项式API
computed: {
count() {
return this.$store.state.count
}
}
// 组合式API
import { computed } from 'vue'
import { useStore } from 'vuex'
const store = useStore()
const count = computed(() => store.state.count)
变更状态(Mutations)[编辑 | 编辑源代码]
唯一修改状态的方式是提交 mutation(同步操作):
mutations: {
increment(state, payload) {
state.count += payload.amount
}
}
// 组件中调用
this.$store.commit('increment', { amount: 10 })
异步操作(Actions)[编辑 | 编辑源代码]
Action 通过提交 mutation 间接变更状态,可包含任意异步操作:
actions: {
async fetchUser({ commit }, userId) {
const user = await api.getUser(userId)
commit('SET_USER', user)
}
}
// 组件中调用
this.$store.dispatch('fetchUser', 'user123')
派生状态(Getters)[编辑 | 编辑源代码]
相当于 store 的计算属性:
getters: {
doubleCount: (state) => state.count * 2,
filteredTodos: (state) => (status) => {
return state.todos.filter(todo => todo.status === status)
}
}
// 使用
this.$store.getters.doubleCount
this.$store.getters.filteredTodos('completed')
数据流图示[编辑 | 编辑源代码]
模块化(Modules)[编辑 | 编辑源代码]
大型应用可将 store 分割为模块:
const userModule = {
namespaced: true,
state: () => ({ profile: {} }),
mutations: { /* ... */ }
}
const store = new Vuex.Store({
modules: {
user: userModule
}
})
// 访问模块状态
this.$store.state.user.profile
实际案例[编辑 | 编辑源代码]
电商购物车实现
// store.js
export default new Vuex.Store({
state: {
cartItems: [],
inventory: {}
},
mutations: {
ADD_TO_CART(state, product) {
const item = state.cartItems.find(i => i.id === product.id)
item ? item.quantity++ : state.cartItems.push({ ...product, quantity: 1 })
}
},
actions: {
async loadInventory({ commit }) {
const products = await fetch('/api/products')
commit('SET_INVENTORY', products)
}
},
getters: {
cartTotal: state => {
return state.cartItems.reduce((sum, item) =>
sum + (item.price * item.quantity), 0)
}
}
})
与Pinia的对比[编辑 | 编辑源代码]
Vuex 4.x 与 Pinia(Vuex 的替代方案)主要区别:
特性 | Vuex | Pinia |
---|---|---|
Vue 版本 | 2.x/3.x | 3.x+ |
类型支持 | 需要额外配置 | 开箱即用 |
模块系统 | 需要命名空间 | 自动命名空间 |
语法复杂度 | 较高 | 更简洁 |
最佳实践[编辑 | 编辑源代码]
1. 遵循单一职责原则拆分模块 2. 使用常量命名 mutation 类型 3. 表单处理建议:
// 使用双向绑定+计算属性
computed: {
message: {
get() { return this.$store.state.obj.message },
set(value) { this.$store.commit('UPDATE_MESSAGE', value) }
}
}
数学表达[编辑 | 编辑源代码]
状态更新可表示为: 其中:
- 为状态
- 为 mutation 函数
- 为 action 负载
常见问题[编辑 | 编辑源代码]
Q: 何时该用 Vuex? A: 当多个组件需要共享状态或存在深层次组件通信时。
Q: 可以直接修改 state 吗? A: 严格模式下会报错,必须通过 mutation 修改。