命名空间的作用是为了减少模块之间定义的方法命名冲突的问题。默认state是局部命名空间 ,mutation、action、getter 是全局命名空间。比如说在a模块getter 中定义一个getter1,在b模块getter 中也定义一个getter1 ,在同一空间内,拥有两个相同的名称,程序会报错。
在模块内定义namespaced:true
。模块所有的mutation、action、getter 则都是局部
const store = Vuex.Stroe({
modules:{
a:{
namespaced:true,
state:{
username:''
}, // a.state
mutations:{
login(state,payload){
state.username= payload.username
}
},
actions:{
login(connext ,payload){
connext.commit('login',payload) //dispatch('a/login')
}
}
}
}
})
子模块默认使用父模块的命名空间。设置namespaced:true
则拥有自己的命名空间。
const store = Vuex.Store({
modules:{
a:{
namespaced:true,
state:{},
actions:{},
modules:{
one_module:{
state:{},
mutations:{
one(){} // 'a/one'
}
},
two_module:{
namespaced:true,
state:{},
mutations:{
qt(){} // 'a/two_module/qt'
}
}
}
}
}
})
如果想在命名空间内,使用全局的state、getter 。提供rootState
和 rootGetters
。
modules:{
foo:{
namespaced:true,
getters:{
some(state, getters, rootState, rootGetters){
rootState.username // 全局state
rootGetters.getter1 // 全局getter1
getters.getter1 //foo/getter1
},
getter1(){}
}
}
}
使用root:true ,让局部化的dispatch 和commit 访问根dispatch 和commit
commit('someMutation', null, { root: true })
dispatch('someOtherAction', null, { root: true })
在带命名空间的模块注册全局 action,可以添加 root: true
,并将这个 action 的定义放在函数 handler
中。
actions: {
action1: {
root: true,
handler (namespacedContext, payload) { }
}
}
使用 createNamespacedHelpers
创建基于某个命名空间辅助函数。
const { mapState, mapActions } = createNamespacedHelpers('a')
computed: {
// 在 `some/nested/module` 中查找
...mapState({
a: state => state.a,
b: state => state.b
})
}
// 载荷方式
this.$store.dispatch('a/login',{
username:'admin'
})
//对象方式
this.$store.dispatch({
type:'a/login',
username:'admin'
})
//直接分发
this.$store.dispatch('a/incrment')
实现一个简单易上手的实例:
1 创建一个store 仓库 ,并且注册两个模块(一个全局,一个局部)。store.js
// vuex version 4.x
import {createStore } from 'vuex'
// 全局
import modelA from './modelA.js'
//局部
import modelB from './modelB.js'
const store = createStore({
modules:{
a:modelA,
b:modelB
}
})
export default store
2 创建一个不带命名空间的模块。modelA.js
const modelA = {
state:{
website_name:'编程领地'
},
mutations:{
setWebsite_name(state ,payload){
state.website_name = payload.website_name
},
getter_g1:state=>state.website_name
}
}
export default modelA
3 创建一个带命名空间的模块。modelB.js
const modelB = {
namespaced:true,
state:{
website_url:'https://www.itboolean.com'
},
mutations:{
setWebsite_Url(state ,payload){
state.website_url = payload.website_url
},
getter1(state,getters ,rootState ,rootGetters){
console.log(state.website_url) //https://
console.log(state,getters ,rootState ,rootGetters)
}
}
}
export default modelB
4 创建一个vue文件,然后分别调用。app.vue
<script setup>
import {computed} from 'vue'
import { useStore ,createNamespacedHelpers } from 'vuex'
const store = useStore()
// 不带命名空间的mutations 使用的全局空间。
store.commit('setWebsite_name' ,{
website_name : '编程领地 good'
})
//访问带命名空间的局部mutations ,带上注册的模块名
store.commit('b/setWebsite_Url',{
website_url:'https://'
})
//调用局部命名空间的getter
store.commit('b/getter1')
//vue 组合式setup 中 使用辅助函数 获取state
const {mapState} = createNamespacedHelpers('b')
const storeStateFns = mapState(['website_url'])
const storeState = {}
Object.keys(storeStateFns).forEach(item => {
const fn = storeStateFns[item].bind({$store: store})
//每个执行一次computed
storeState[item] = computed(fn)
})
</script>
<template>
<div>
<div>
标题:{{store.state.a.website_name}}
</div>
<div>
链接:{{store.state.b.website_url}}
</div>
{{storeState.website_url}}
</div>
</template>