Mutation基础 #
什么是 Mutation? #
Mutation 是 Vuex 中更改状态的唯一方法。每个 mutation 都有一个字符串的事件类型 (type) 和一个回调函数 (handler)。这个回调函数就是我们实际进行状态更改的地方,并且它会接受 state 作为第一个参数。
定义 Mutation #
基本语法 #
javascript
const store = createStore({
state: {
count: 0
},
mutations: {
// mutation 函数
INCREMENT(state) {
state.count++
},
DECREMENT(state) {
state.count--
}
}
})
使用常量命名 #
推荐使用常量作为 mutation 类型名:
javascript
// mutation-types.js
export const INCREMENT = 'INCREMENT'
export const DECREMENT = 'DECREMENT'
export const SET_COUNT = 'SET_COUNT'
export const SET_USER = 'SET_USER'
// store.js
import { INCREMENT, DECREMENT, SET_COUNT, SET_USER } from './mutation-types'
const store = createStore({
state: {
count: 0,
user: null
},
mutations: {
[INCREMENT](state) {
state.count++
},
[DECREMENT](state) {
state.count--
},
[SET_COUNT](state, value) {
state.count = value
},
[SET_USER](state, user) {
state.user = user
}
}
})
提交 Mutation #
普通提交 #
javascript
// 在组件中
this.$store.commit('INCREMENT')
// 带 payload
this.$store.commit('SET_COUNT', 10)
对象风格提交 #
javascript
this.$store.commit({
type: 'SET_COUNT',
value: 10
})
在 Action 中提交 #
javascript
actions: {
increment({ commit }) {
commit('INCREMENT')
},
setCount({ commit }, value) {
commit('SET_COUNT', value)
}
}
Payload 载荷 #
单一参数 #
javascript
mutations: {
SET_COUNT(state, value) {
state.count = value
}
}
// 提交
this.$store.commit('SET_COUNT', 10)
对象参数 #
javascript
mutations: {
UPDATE_USER(state, payload) {
state.user = {
...state.user,
...payload
}
}
}
// 提交
this.$store.commit('UPDATE_USER', {
name: 'John',
age: 25
})
解构参数 #
javascript
mutations: {
UPDATE_USER(state, { name, age }) {
state.user.name = name
state.user.age = age
}
}
// 提交
this.$store.commit('UPDATE_USER', {
name: 'John',
age: 25
})
Mutation 规则 #
1. 必须是同步函数 #
javascript
// 错误:异步 mutation
mutations: {
INCREMENT(state) {
setTimeout(() => {
state.count++ // 不要这样做
}, 1000)
}
}
// 正确:同步 mutation
mutations: {
INCREMENT(state) {
state.count++
}
}
// 异步操作应该放在 action 中
actions: {
async incrementAsync({ commit }) {
await delay(1000)
commit('INCREMENT')
}
}
2. 不要直接调用 mutation #
javascript
// 错误:直接调用
this.$store.mutations.INCREMENT(state)
// 正确:通过 commit
this.$store.commit('INCREMENT')
3. 使用 Vue.set 处理新属性 #
javascript
mutations: {
ADD_PROPERTY(state, { key, value }) {
// 错误:直接添加属性不会触发响应式
// state.user[key] = value
// 正确:使用 Vue.set 或对象展开
state.user = { ...state.user, [key]: value }
}
}
常见 Mutation 模式 #
设置值 #
javascript
mutations: {
SET_USER(state, user) {
state.user = user
},
SET_LOADING(state, loading) {
state.loading = loading
},
SET_ERROR(state, error) {
state.error = error
}
}
添加项 #
javascript
mutations: {
ADD_TODO(state, todo) {
state.todos.push(todo)
},
ADD_TO_CART(state, item) {
state.cart.push(item)
}
}
删除项 #
javascript
mutations: {
REMOVE_TODO(state, id) {
const index = state.todos.findIndex(t => t.id === id)
if (index !== -1) {
state.todos.splice(index, 1)
}
},
CLEAR_CART(state) {
state.cart = []
}
}
更新项 #
javascript
mutations: {
UPDATE_TODO(state, { id, updates }) {
const index = state.todos.findIndex(t => t.id === id)
if (index !== -1) {
state.todos[index] = {
...state.todos[index],
...updates
}
}
},
TOGGLE_TODO(state, id) {
const todo = state.todos.find(t => t.id === id)
if (todo) {
todo.done = !todo.done
}
}
}
切换状态 #
javascript
mutations: {
TOGGLE_SIDEBAR(state) {
state.sidebarOpen = !state.sidebarOpen
},
TOGGLE_THEME(state) {
state.theme = state.theme === 'light' ? 'dark' : 'light'
}
}
使用 mapMutations #
数组语法 #
javascript
import { mapMutations } from 'vuex'
export default {
methods: {
...mapMutations([
'INCREMENT',
'DECREMENT',
'SET_COUNT'
])
}
}
// 使用
this.INCREMENT()
this.SET_COUNT(10)
对象语法 #
javascript
import { mapMutations } from 'vuex'
export default {
methods: {
...mapMutations({
add: 'INCREMENT',
subtract: 'DECREMENT',
set: 'SET_COUNT'
})
}
}
// 使用
this.add()
this.set(10)
模块中的使用 #
javascript
import { mapMutations } from 'vuex'
export default {
methods: {
...mapMutations('user', [
'SET_USER',
'CLEAR_USER'
]),
...mapMutations('cart', {
addToCart: 'ADD_ITEM',
clearCart: 'CLEAR'
})
}
}
组合式 API 中使用 #
vue
<script>
import { useStore } from 'vuex'
export default {
setup() {
const store = useStore()
const increment = () => {
store.commit('INCREMENT')
}
const setCount = (value) => {
store.commit('SET_COUNT', value)
}
return {
increment,
setCount
}
}
}
</script>
实战示例 #
用户状态管理 #
javascript
// store/modules/user.js
export default {
namespaced: true,
state: {
user: null,
token: null,
loading: false,
error: null
},
mutations: {
SET_USER(state, user) {
state.user = user
},
SET_TOKEN(state, token) {
state.token = token
},
SET_LOADING(state, loading) {
state.loading = loading
},
SET_ERROR(state, error) {
state.error = error
},
CLEAR_USER(state) {
state.user = null
state.token = null
},
CLEAR_ERROR(state) {
state.error = null
}
}
}
购物车状态管理 #
javascript
// store/modules/cart.js
export default {
namespaced: true,
state: {
items: [],
couponCode: null
},
mutations: {
ADD_ITEM(state, { product, quantity = 1 }) {
const existingItem = state.items.find(i => i.productId === product.id)
if (existingItem) {
existingItem.quantity += quantity
} else {
state.items.push({
productId: product.id,
product,
quantity
})
}
},
REMOVE_ITEM(state, productId) {
const index = state.items.findIndex(i => i.productId === productId)
if (index !== -1) {
state.items.splice(index, 1)
}
},
UPDATE_QUANTITY(state, { productId, quantity }) {
const item = state.items.find(i => i.productId === productId)
if (item) {
item.quantity = quantity
}
},
SET_COUPON(state, code) {
state.couponCode = code
},
CLEAR_CART(state) {
state.items = []
state.couponCode = null
}
}
}
总结 #
Mutation 核心要点:
| 要点 | 说明 |
|---|---|
| 同步性 | 必须是同步函数 |
| 提交方式 | 通过 commit 调用 |
| 参数传递 | 使用 payload 对象 |
| 命名规范 | 使用常量命名 |
继续学习 提交风格,了解不同的提交方式。
最后更新:2026-03-28