模块化+命名空间
Vuex中的高级写法:Vuex的模块化编码
把不同分类【业务分类不同,比如订单管理类的和商品管理类的】的mutation放在不同位置
模块化编码的最终目标:对actions、mutations、state、getters中的内容进行分类整理
1. Vuex模块化编码的步骤
-
根据业务分类划分模块,在store配置文件【index.js】中将同一模块下的配置封装为一个对象,对象名自行定义
// 模块:求和,包含了求和组件Count相关的配置 const qiuhe = { actions: { }, mutations:{ }, state:{ }, getters:{ } } // 模块:人员,包含了人员组件Person相关的配置 const person = { actions: { }, mutations:{ }, state:{ }, getters:{ } }
-
为每个模块定义自己的actions、mutations、state、getters以及namespaced
const qiuhe = { // 要想在组件中通过map方法生成代码时指定模块,需要vuex的模块化配置中添加namespaced配置项,如果不写,该配置项的默认值是false namespaced: true, actions: { conditionAdd(context,value){ if(context.state.sumNumber % 2){ context.commit('JIA',value) } }, addLater(context,value){ setTimeout(()=>{ context.commit('JIA',value) },500) } }, mutations:{ JIA(state,value){ state.sumNumber = value + state.sumNumber }, JIAN(state,value){ state.sumNumber = state.sumNumber - value }, }, state:{ sumNumber: 0, str1: '自', str2: '前端', }, getters:{ bigNum(state){ return state.sumNumber * 10 } } } const person = { namespaced: true, actions: { }, mutations:{ ADD(state,value){ var p = {} p.id = '002' p.name = value state.persons.push(p) } }, state:{ persons: [ {id: '001', name: '张三'}, ] }, getters:{ } }
-
创建store实例时传入modules配置项,值为由各个模块组成的对象
// 在store中配置getters export default new Vuex.Store({ modules:{ a:qiuhe, b:person } })
-
调用map方法时指明模块即可
import {mapState,mapGetters,mapMutations,mapActions} from 'vuex' export default { name: 'Count', data(){ return { selectedNumber: 0, } }, computed:{ // 第一个参数用于指明模块 // 指明模块的好处是在模板中可以直接使用sumNumber、str1、str2 // 否则,就要像这样去生成代码 // ...mapState(['a']) // 这样,模板中就要a.sumNumber的方式使用模块下的配置项 ...mapState('a',['sumNumber','str1','str2']), ...mapState('b',['persons']), ...mapGetters('a',['bigNum']) }, methods:{ ...mapMutations('a',{addition:'JIA',subscribe:'JIAN'}), ...mapActions('a',{conditionAdd:'conditionAdd',addLater:'addLater'}) }, mounted() { console.log(this.$store) } }
-
模板中就可以直接使用state、getters...中的属性和方法
<template> <div> <!-- 模板中获取state中的数据 --> <h1>当前求和为:{{sumNumber}}</h1> <h3>当前求和放大10倍为:{{bigNum}}</h3> <h4>我在{{str1}}学{{str2}}</h4> <div> <select v-model="selectedNumber"> <option :value="1">1</option> <option :value="2">2</option> <option :value="3">3</option> </select> <button type="button" @click="addition(selectedNumber)">+</button> <button type="button" @click="subscribe(selectedNumber)">-</button> <button type="button" @click="conditionAdd(selectedNumber)">当前和为奇数再加</button> <button type="button" @click="addLater(selectedNumber)">等一等再加</button> </div> <hr > <ul> <li v-for="person in persons" :key="person.id">{{person.name}}</li> </ul> </div> </template>
-
除此之外,index.js中拆分出来的各个模块可以都独立为一个一个的单独的配置文件,增强可维护性
建立两个以步骤二中模块命名的js文件,分别是store/qiuhe.js和store/person.js
-
将index.js中两个模块的代码分别放到上个步骤创建的js文件中,并通过export default默认暴露的方式暴露对象
以store/person.js为例
const person = { namespaced: true, actions: { }, mutations:{ ADD(state,value){ var p = {} p.id = '002' p.name = value state.persons.push(p) } }, state:{ persons: [ {id: '001', name: '张三'}, ] }, getters:{ } } export default person
-
index中导入store/qiuhe.js和store/person.js使用即可
import Vue from 'vue' import Vuex from 'vuex' import qiuhe from './qiuhe.js' import person from './person.js' Vue.use(Vuex) // 在store中配置getters export default new Vuex.Store({ modules:{ a:qiuhe, b:person } })
2. 使用Vuex模块化编码后,如果不借用四个map方法,我们应该怎样使用Vuex?
computed:{
sumNumber(){
// 获取模块a中state中的sumNumber
return this.$store.state.a.sumNumber
},
str1(){
return this.$store.state.a.str1
},
str2(){
return this.$store.state.a.str2
},
bigNum(){
// 获取模块a中getters中的bigNum
return this.$store.getters['a/bigNum']
},
persons(){
// 获取模块b中state中的persons
return this.$store.state.b.persons
}
},
methods:{
addition(value){
// 调用模块a的mutations中的JIA()
this.$store.commit('a/JIA',value)
},
subscribe(value){
this.$store.commit('a/JIAN',value)
},
conditionAdd(value){
// 调用模块a的actions中的conditionAdd()
this.$store.dispatch('a/conditionAdd',value)
},
addLater(value){
this.$store.dispatch('a/addLater',value)
}
}
3. Vuex模块化编码的好处
-
不同业务场景的mutation和action糅合在一起非常臃肿,不好维护,模块化编码可以将拆出的每一个模块都单独作为一个配置文件,更易维护。
-
不使用模块化,多个程序员操作mutation或action操作的都是同一个,容易造成git版本控制冲突。
-
使用模块化可以避免命名冲突,不同模块中使用同名的变量或方法互相之间不受影响。
4. 总结
-
目的:让代码更好维护,让多种数据分类更加明确。
-
修改
store.js
const countAbout = { namespaced:true,//开启命名空间 state:{x:1}, mutations: { ... }, actions: { ... }, getters: { bigSum(state){ return state.sum * 10 } } } const personAbout = { namespaced:true,//开启命名空间 state:{ ... }, mutations: { ... }, actions: { ... } } const store = new Vuex.Store({ modules: { countAbout, personAbout } })
-
开启命名空间后,组件中读取state数据:
//方式一:自己直接读取 this.$store.state.personAbout.list //方式二:借助mapState读取: ...mapState('countAbout',['sum','school','subject']),
-
开启命名空间后,组件中读取getters数据:
//方式一:自己直接读取 this.$store.getters['personAbout/firstPersonName'] //方式二:借助mapGetters读取: ...mapGetters('countAbout',['bigSum'])
-
开启命名空间后,组件中调用dispatch
//方式一:自己直接dispatch this.$store.dispatch('personAbout/addPersonWang',person) //方式二:借助mapActions: ...mapActions('countAbout',{incrementOdd:'jiaOdd',incrementWait:'jiaWait'})
-
开启命名空间后,组件中调用commit
//方式一:自己直接commit this.$store.commit('personAbout/ADD_PERSON',person) //方式二:借助mapMutations: ...mapMutations('countAbout',{increment:'JIA',decrement:'JIAN'}),