What exactly is namespacing of modules in vuex
When you have a big app with a very large state object, you will often divide it into modules.
Which basically means you break the state into smaller pieces. One of the caveats is that you can't use the same method name for a module since it is integrated into the same state, so for example:
moduleA {
actions:{
save(){}
}
}
moduleB {
actions:{
//this will throw an error that you have the same action defined twice
save(){}
}
}
So in order to enable this you have the option to define the module as namespaced, and then you can use the same method in different modules:
moduleA {
actions:{
save(){}
},
namespaced: true
}
moduleB {
actions:{
save(){}
},
namespaced: true
}
and then you call it like this:
this.$store.dispatch('moduleA/save')
this.$store.dispatch('moduleB/save')
Please note that it might complicate things a bit if you're using mapGetter
or mapActions
since the getters are now in the form of ['moduleA/client']
So use it only if you really need to.
To using it, we can pass the module namespace string as the first argument to the helpers so that all bindings are done using that module as the context. The above can be simplified to:
...mapGetter('moduleA/client', {
a: state => state.a
});
By default, Vuex registers all getters, actions in the global namespace. The global Vuex namespace will face the conflicts as the Vuex modules grow in large numbers. The namespacing approach comes into picture to resolve this issue. The namespaced module won't get registered in the global namespace. instead, it's available under the specific module namespace
.
Consider the example having two module products and cart,
//products module
export default {
namespaced: true,
state: {
products: []
},
getters: {
products(state){
return state.products
}
},
actions: {
async load(context, params){ ... }
},
mutations: {
products(state, data){ ... }
}
}
and another module having similar getters and actions,
//cart module
export default {
namespaced: true,
state: {
products: [],
cart: []
},
getters: {
products(state){ return state.products }
cart(state){ return state.cart}
},
actions: {
async load(context, params){ ... },
async set(context, params){ ... },
},
mutations: {
products(state, data){ ... },
cart(state, data){ ... }
}
}
Both products
and cart
module have a getter product and action load in common. If you use such a module without namespacing, it will create issues. Here making namespaced: true
in the root of the module helps to recover such a situation.
You can map the getters using namespace as ...mapGetters(['products/products'])
and same applies for mapActions
too.
I'm not an expert in vue.js but as I can see in the docs namespacing can be used to modify the path access to a module's getters/actions/mutations.
By default namespaced: false
all of the getters, actions, mutations are available globally by the different modules so if you want to use the same getter/action/mutation in different modules you must flag them as namespaced: true
, otherwise an error will be thrown.
Another use of this is to organize your getters/actions/mutations in different paths (the one that a module is registered at). This is very useful in large projects because you can know right away where the getter/action/mutation is defined so its easier to locate them.