命名空间 #
什么是命名空间? #
默认情况下,模块内部的 action、mutation 和 getter 是注册在全局命名空间的。开启命名空间后,模块会更有封装性和复用性。
开启命名空间 #
基本用法 #
javascript
const moduleA = {
namespaced: true, // 开启命名空间
state: () => ({ ... }),
mutations: { ... },
actions: { ... },
getters: { ... }
}
命名空间效果 #
javascript
const store = createStore({
modules: {
user: {
namespaced: true,
state: () => ({ name: 'John' }),
mutations: {
SET_NAME(state, name) {
state.name = name
}
},
actions: {
fetchUser({ commit }) {
// ...
}
},
getters: {
userName: state => state.name
}
}
}
})
// 访问方式改变
store.state.user.name // state 不变
store.commit('user/SET_NAME') // mutation 需要加前缀
store.dispatch('user/fetchUser') // action 需要加前缀
store.getters['user/userName'] // getter 需要加前缀
在组件中使用 #
直接访问 #
javascript
// State
this.$store.state.user.name
// Mutation
this.$store.commit('user/SET_NAME', 'Jane')
// Action
this.$store.dispatch('user/fetchUser')
// Getter
this.$store.getters['user/userName']
使用辅助函数 #
javascript
import { mapState, mapGetters, mapMutations, mapActions } from 'vuex'
export default {
computed: {
// 指定模块命名空间
...mapState('user', ['name']),
...mapGetters('user', ['userName'])
},
methods: {
...mapMutations('user', ['SET_NAME']),
...mapActions('user', ['fetchUser'])
}
}
使用 createNamespacedHelpers #
javascript
import { createNamespacedHelpers } from 'vuex'
// 创建基于某个命名空间的辅助函数
const { mapState, mapGetters, mapMutations, mapActions } =
createNamespacedHelpers('user')
export default {
computed: {
// 无需再指定命名空间
...mapState(['name']),
...mapGetters(['userName'])
},
methods: {
...mapMutations(['SET_NAME']),
...mapActions(['fetchUser'])
}
}
在模块内访问全局内容 #
访问全局 Action #
javascript
const moduleA = {
namespaced: true,
actions: {
// 局部 action
someAction({ commit, dispatch }) {
// 调用局部 mutation
commit('SET_DATA', data)
// 调用全局 action
dispatch('globalAction', null, { root: true })
// 调用其他模块的 action
dispatch('user/login', credentials, { root: true })
}
}
}
访问全局 Mutation #
javascript
actions: {
someAction({ commit }) {
// 调用局部 mutation
commit('SET_LOCAL_DATA', data)
// 调用全局 mutation
commit('SET_GLOBAL_DATA', data, { root: true })
// 调用其他模块的 mutation
commit('user/SET_NAME', name, { root: true })
}
}
注册全局 Action #
javascript
const moduleA = {
namespaced: true,
actions: {
// 局部 action
localAction({ commit }) {
// ...
},
// 注册全局 action
globalAction: {
root: true, // 注册到全局
handler({ commit }) {
// ...
}
}
}
}
// 调用
this.$store.dispatch('globalAction') // 不需要命名空间前缀
注册全局 Mutation #
javascript
const moduleA = {
namespaced: true,
mutations: {
// 局部 mutation
SET_LOCAL_DATA(state, data) {
// ...
}
}
}
// 如果需要全局 mutation,在模块外定义
const store = createStore({
modules: {
moduleA
},
mutations: {
SET_GLOBAL_DATA(state, data) {
// ...
}
}
})
带命名空间的绑定函数 #
简化绑定 #
javascript
import { createNamespacedHelpers } from 'vuex'
const { mapState, mapGetters, mapMutations, mapActions } =
createNamespacedHelpers('user')
export default {
computed: {
...mapState({
name: state => state.name,
email: state => state.email
}),
...mapGetters([
'isLoggedIn',
'userName'
])
},
methods: {
...mapMutations([
'SET_NAME',
'SET_EMAIL'
]),
...mapActions([
'login',
'logout'
])
}
}
重命名 #
javascript
const { mapState, mapActions } = createNamespacedHelpers('user')
export default {
computed: {
...mapState({
currentUserName: 'name',
currentUserEmail: 'email'
})
},
methods: {
...mapActions({
signIn: 'login',
signOut: 'logout'
})
}
}
嵌套模块的命名空间 #
定义嵌套模块 #
javascript
const store = createStore({
modules: {
account: {
namespaced: true,
state: () => ({ ... }),
mutations: { ... },
actions: { ... },
getters: { ... },
modules: {
posts: {
namespaced: true,
state: () => ({ ... }),
mutations: { ... }
},
comments: {
namespaced: true,
state: () => ({ ... }),
mutations: { ... }
}
}
}
}
})
// 访问嵌套模块
store.state.account.posts
store.commit('account/posts/SET_POSTS', posts)
store.dispatch('account/posts/fetchPosts')
store.getters['account/posts/allPosts']
使用辅助函数 #
javascript
import { createNamespacedHelpers } from 'vuex'
const { mapState, mapActions } = createNamespacedHelpers('account/posts')
export default {
computed: {
...mapState(['items'])
},
methods: {
...mapActions(['fetchPosts'])
}
}
实战示例 #
用户模块 #
javascript
// store/modules/user.js
export default {
namespaced: true,
state: () => ({
profile: null,
token: null,
loading: false
}),
mutations: {
SET_PROFILE(state, profile) {
state.profile = profile
},
SET_TOKEN(state, token) {
state.token = token
},
SET_LOADING(state, loading) {
state.loading = loading
}
},
actions: {
async login({ commit }, credentials) {
commit('SET_LOADING', true)
try {
const { user, token } = await api.login(credentials)
commit('SET_PROFILE', user)
commit('SET_TOKEN', token)
return user
} finally {
commit('SET_LOADING', false)
}
},
logout({ commit }) {
commit('SET_PROFILE', null)
commit('SET_TOKEN', null)
}
},
getters: {
isLoggedIn: state => !!state.token,
userName: state => state.profile?.name || 'Guest'
}
}
组件中使用 #
vue
<template>
<div>
<p v-if="isLoggedIn">Welcome, {{ userName }}</p>
<button @click="login({ username, password })">Login</button>
<button @click="logout">Logout</button>
</div>
</template>
<script>
import { createNamespacedHelpers } from 'vuex'
const { mapState, mapGetters, mapActions } =
createNamespacedHelpers('user')
export default {
data() {
return {
username: '',
password: ''
}
},
computed: {
...mapState(['loading']),
...mapGetters(['isLoggedIn', 'userName'])
},
methods: {
...mapActions(['login', 'logout'])
}
}
</script>
最佳实践 #
1. 始终开启命名空间 #
javascript
// 推荐
export default {
namespaced: true,
// ...
}
// 不推荐(除非有特殊需求)
export default {
namespaced: false,
// ...
}
2. 使用 createNamespacedHelpers #
javascript
// 推荐:更简洁
const { mapState, mapActions } = createNamespacedHelpers('user')
// 不推荐:重复写命名空间
...mapState('user', ['name'])
...mapActions('user', ['login'])
3. 模块命名清晰 #
javascript
// 推荐:清晰的模块名
modules: {
user,
cart,
products,
orders
}
// 不推荐:模糊的模块名
modules: {
module1,
module2,
data
}
总结 #
命名空间使用要点:
| 操作 | 无命名空间 | 有命名空间 |
|---|---|---|
| State | state.module |
state.module |
| Mutation | commit('MUTATION') |
commit('module/MUTATION') |
| Action | dispatch('action') |
dispatch('module/action') |
| Getter | getters.getter |
getters['module/getter'] |
继续学习 模块注册,了解动态注册模块。
最后更新:2026-03-28