Action基础 #
什么是 Action? #
Action 类似于 Mutation,不同在于:
- Action 提交的是 Mutation,而不是直接变更状态
- Action 可以包含任意异步操作
定义 Action #
基本语法 #
javascript
const store = createStore({
state: {
count: 0
},
mutations: {
INCREMENT(state) {
state.count++
}
},
actions: {
// Action 函数接收 context 对象
increment(context) {
context.commit('INCREMENT')
}
}
})
使用解构 #
javascript
actions: {
// 解构 context 对象
increment({ commit }) {
commit('INCREMENT')
},
// 解构更多属性
decrement({ commit, state, getters }) {
if (getters.canDecrement) {
commit('DECREMENT')
}
}
}
context 对象 #
context 对象包含以下属性:
javascript
actions: {
example(context) {
// context.state - 当前状态
// context.rootState - 根状态
// context.getters - 当前 getters
// context.rootGetters - 根 getters
// context.commit - 提交 mutation
// context.dispatch - 分发 action
}
}
分发 Action #
普通分发 #
javascript
// 在组件中
this.$store.dispatch('increment')
// 带 payload
this.$store.dispatch('setCount', 10)
对象风格分发 #
javascript
this.$store.dispatch({
type: 'setCount',
value: 10
})
在 Action 中分发 #
javascript
actions: {
actionA({ commit }) {
commit('SET_DATA')
},
actionB({ dispatch }) {
dispatch('actionA') // 分发其他 action
}
}
Action vs Mutation #
| 特性 | Mutation | Action |
|---|---|---|
| 直接修改状态 | 是 | 否 |
| 异步操作 | 不允许 | 允许 |
| 调用方式 | commit | dispatch |
| 返回值 | 无 | Promise |
| 调试 | 时间旅行 | 记录调用 |
异步操作 #
基本异步 #
javascript
actions: {
async fetchUser({ commit }, userId) {
const response = await fetch(`/api/users/${userId}`)
const user = await response.json()
commit('SET_USER', user)
}
}
完整示例 #
javascript
const store = createStore({
state: {
user: null,
loading: false,
error: null
},
mutations: {
SET_USER(state, user) {
state.user = user
},
SET_LOADING(state, loading) {
state.loading = loading
},
SET_ERROR(state, error) {
state.error = error
}
},
actions: {
async fetchUser({ commit }, userId) {
commit('SET_LOADING', true)
commit('SET_ERROR', null)
try {
const response = await fetch(`/api/users/${userId}`)
if (!response.ok) throw new Error('Failed to fetch user')
const user = await response.json()
commit('SET_USER', user)
} catch (error) {
commit('SET_ERROR', error.message)
} finally {
commit('SET_LOADING', false)
}
}
}
})
返回 Promise #
Action 默认返回 Promise:
javascript
actions: {
async fetchUser({ commit }, userId) {
const user = await api.fetchUser(userId)
commit('SET_USER', user)
return user
}
}
// 使用
this.$store.dispatch('fetchUser', 1)
.then(user => {
console.log('User:', user)
})
.catch(error => {
console.error('Error:', error)
})
// 或 async/await
async loadUser() {
try {
const user = await this.$store.dispatch('fetchUser', 1)
console.log('User:', user)
} catch (error) {
console.error('Error:', error)
}
}
使用 mapActions #
数组语法 #
javascript
import { mapActions } from 'vuex'
export default {
methods: {
...mapActions([
'fetchUser',
'login',
'logout'
])
}
}
// 使用
this.fetchUser(1)
this.login({ username, password })
对象语法 #
javascript
import { mapActions } from 'vuex'
export default {
methods: {
...mapActions({
loadUser: 'fetchUser',
signIn: 'login',
signOut: 'logout'
})
}
}
组合式 API 中使用 #
vue
<script>
import { useStore } from 'vuex'
export default {
setup() {
const store = useStore()
const fetchUser = async (userId) => {
return await store.dispatch('fetchUser', userId)
}
return {
fetchUser
}
}
}
</script>
实战示例 #
用户认证 #
javascript
// store/modules/auth.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_AUTH(state) {
state.user = null
state.token = null
}
},
actions: {
async login({ commit }, credentials) {
commit('SET_LOADING', true)
commit('SET_ERROR', null)
try {
const response = await api.login(credentials)
commit('SET_USER', response.user)
commit('SET_TOKEN', response.token)
localStorage.setItem('token', response.token)
return response.user
} catch (error) {
commit('SET_ERROR', error.message)
throw error
} finally {
commit('SET_LOADING', false)
}
},
async logout({ commit }) {
await api.logout()
localStorage.removeItem('token')
commit('CLEAR_AUTH')
},
async checkAuth({ commit }) {
const token = localStorage.getItem('token')
if (!token) return false
try {
const user = await api.getCurrentUser()
commit('SET_USER', user)
commit('SET_TOKEN', token)
return true
} catch {
commit('CLEAR_AUTH')
return false
}
}
}
}
数据获取 #
javascript
// store/modules/products.js
export default {
namespaced: true,
state: {
items: [],
current: null,
loading: false,
error: null
},
mutations: {
SET_ITEMS(state, items) {
state.items = items
},
SET_CURRENT(state, item) {
state.current = item
},
ADD_ITEM(state, item) {
state.items.push(item)
},
UPDATE_ITEM(state, updatedItem) {
const index = state.items.findIndex(i => i.id === updatedItem.id)
if (index !== -1) {
state.items[index] = updatedItem
}
},
REMOVE_ITEM(state, id) {
state.items = state.items.filter(i => i.id !== id)
},
SET_LOADING(state, loading) {
state.loading = loading
},
SET_ERROR(state, error) {
state.error = error
}
},
actions: {
async fetchAll({ commit }, filters = {}) {
commit('SET_LOADING', true)
commit('SET_ERROR', null)
try {
const items = await api.getProducts(filters)
commit('SET_ITEMS', items)
return items
} catch (error) {
commit('SET_ERROR', error.message)
throw error
} finally {
commit('SET_LOADING', false)
}
},
async fetchOne({ commit }, id) {
commit('SET_LOADING', true)
try {
const item = await api.getProduct(id)
commit('SET_CURRENT', item)
return item
} catch (error) {
commit('SET_ERROR', error.message)
throw error
} finally {
commit('SET_LOADING', false)
}
},
async create({ commit }, data) {
commit('SET_LOADING', true)
try {
const item = await api.createProduct(data)
commit('ADD_ITEM', item)
return item
} catch (error) {
commit('SET_ERROR', error.message)
throw error
} finally {
commit('SET_LOADING', false)
}
},
async update({ commit }, { id, data }) {
commit('SET_LOADING', true)
try {
const item = await api.updateProduct(id, data)
commit('UPDATE_ITEM', item)
return item
} catch (error) {
commit('SET_ERROR', error.message)
throw error
} finally {
commit('SET_LOADING', false)
}
},
async remove({ commit }, id) {
commit('SET_LOADING', true)
try {
await api.deleteProduct(id)
commit('REMOVE_ITEM', id)
} catch (error) {
commit('SET_ERROR', error.message)
throw error
} finally {
commit('SET_LOADING', false)
}
}
}
}
总结 #
Action 核心要点:
| 要点 | 说明 |
|---|---|
| 异步处理 | Action 用于处理异步操作 |
| 提交 Mutation | 通过 commit 修改状态 |
| 返回 Promise | Action 返回 Promise |
| 分发方式 | 通过 dispatch 调用 |
继续学习 异步操作,深入了解异步处理技巧。
最后更新:2026-03-28