vuex 多模块时 模块内部的mutation和action的调用方式
vue在做大型项目时,会用到多状态管理,vuex允许我们将store分割成多个模块,每个模块内都有自己的state、mutation、action、getter。模块内还可以继续嵌套相对应的子模块。为了巩固我自己对store多模块的一些基本认识,写了个简单的多模块实例,下图为我自己创建的store的目录结构,modules文件夹内的模块,在实际项目中还可以继续分开类似store目录下的多文件结..
vue在做大型项目时,会用到多状态管理,vuex允许我们将store分割成多个模块,每个模块内都有自己的state、mutation、action、getter。模块内还可以继续嵌套相对应的子模块。
为了巩固我自己对store多模块的一些基本认识,写了个简单的多模块实例,下图为我自己创建的store的目录结构,modules文件夹内的模块,在实际项目中还可以继续分开类似store目录下的多文件结构,也就是单独的模块文件夹,方便后期修改。
./store/index.js的代码如下:
import Vue from 'vue'
import Vuex from 'vuex'
// import mutations from './mutations'
import modulesA from './modules/modulesA'
import modulesB from './modules/modulesB'
Vue.use(Vuex)
const state = {
logined: false,
userid: -1
}
const store = new Vuex.Store({
state,
mutations: {
'UPDATE_LOGIN_STATUS': (state, payload) => {
state.logined = true
}
},
modules: {
modulesA: modulesA,
modulesB: modulesB
}
})
export default store
这里为了方便和子模块进行对比,我将mutations.js的代码放到index.js里面
modulesA.js的代码如下:
const moduleA = {
namespaced: true,
state: {
isVip1: false
},
mutations: {
'UPDATE_TO_VIP1': (state, payload) => {
state.isVip1 = true
}
},
actions: {
getVip1 ({ state, commit, rootState }) {
commit('UPDATE_TO_VIP1')
}
},
getters: {}
}
export default moduleA
modulesB.js的代码如下:
const moduleB = {
// namespaced: true,
state: {
isVip2: false
},
mutations: {
'UPDATE_TO_VIP2': (state, payload) => {
state.isVip2 = true
}
},
actions: {
getVip2 ({ state, commit, rootState }) {
commit('UPDATE_TO_VIP2')
}
},
getters: {}
}
export default moduleB
估计看到这里,你会发现modulesA和modulesB的区别就是有无namespaced这个属性。在vuex内,模块内部的action、mutation、getter都会被注册在全局命名空间内,俗话就是注册成全局的,这样做的结果就是在调用相对应的名字的的action或者mutation或者getter的时候,所有同名的都将会被响应。让我们来看看当没有namespaced(或者值为false)的时候,在组件内是怎么调用的,这里代码如下:
<template>
<div class="hello">
<h1>{{ msg }}</h1>
<ul>
<li>global state <strong>logined</strong>: {{ globalState }}</li>
<li>modulesA state <strong>isVip1</strong> {{ modulesAState }}</li>
</ul>
</div>
</template>
<script>
export default {
name: 'test',
data () {
return {
msg: 'Test vuex mutilple modules'
}
},
created () {
console.log(this.$store.state)
setTimeout(() => {
this.$store.commit('UPDATE_LOGIN_STATUS')
}, 1000)
setTimeout(() => {
this.$store.commit('UPDATE_TO_VIP1')
// this.$store.dispatch('getVip1')
}, 2000)
setTimeout(() => {
// this.$store.commit('CANCEL_VIP1')
this.$store.dispatch('cancelVip1')
}, 3000)
},
computed: {
globalState () {
return this.$store.state.logined
},
modulesAState () {
return this.$store.state.modulesA.isVip1
}
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
</style>
执行代码的截图如下:
可以看到,我在store里面commit一个UPDATE_LOGIN_STATUS,将最顶层state中的logined的值改为true。2s的时候在store里面commit了UPDATE_TO_VIP1和3s的时候dispatch了一个事件CANCEL_VIP1,将modulesA的isVip1的值从false => true => false。说明没有开启命名空间是可以直接commit或者dispatch子模块内相对应的方法名,是可以修改到自身state中的属性的。
如果namespaced的值为true时,那么就是开启了命名空间模块,调用子模块的getter、mutation、getter的时候就跟之前不一样了,vuex它内部会自动根据模块注册的路径调整命名,比如要dispatch B中的一个action的话,那么组件内的调用就应该是如下这样的:
// this.$store.dispatch('modulesB/getVip2')
this.$store.commit('modulesB/UPDATE_TO_VIP2')
日常项目中,在store有多个状态需要管理的时候,一般来说是应该要开启namespaced的,这样子能够使我们的代码能够有更强的封装性以及更少的耦合。
更多推荐
所有评论(0)