代码优化
01 - 为什么需要优化
使用Vuex之后会发现在使用store
管理的数据时有些繁琐,模板的插值表达式中,每个被使用的数据都必须$store.state.属性名
,假如我们有100个数据,$store.state
就得写100遍,感觉非常没必要,造成了资源浪费,也会使加载速度变慢。
这时就会有人想到Vue的计算属性computed
,写着写着又发现,即使是计算属性的简写形式也是每一个数据都需要写一个方法的,依然很繁琐。
接下来要说的就是Vuex给我们提供了辅助函数(mapState等),可以帮助我们生成计算属性等,极大的减少了代码量和工作量,又能少掉几根头发啦啦啦。
02 - 使用方法
引入辅助函数
import {mapState,mapGetters,mapMutations,mapActions} from vuex
介绍一下这四位新朋友
1、mapState
用于帮助我们映射state
中的数据为计算属性
2、mapGetters
用于帮助我们映射getters
中的数据为计算属性
3、mapActions
用于帮助我们生成与actions
对话的方法,即包含$store.dispatch(xxx)
的函数,传递的参数需要在绑定事件时携带,否则参数是事件对象
4、mapMutations
用于帮助我们生成与mutations
对话的方法,即包含$store.commit(xxx)
的函数,传递的参数需要在绑定事件时携带,否则参数是事件对象
使用辅助函数
使用时可以有对象写法和数组写法两种,其中数组写法需要自定义计算属性名与state
中对应属性名一致,且用的相对来说比较多,所以把对象写法全注掉了,只把数组写法放出来了,注意这里数组项都是字符串哦
这里的“...”看不懂的建议去复习一下es6的对象扩展运算符(用于取出参数对象所有可遍历属性然后拷贝到当前对象),这里就不再赘述了。
computed:{
//借助mapState生成计算属性,从state中读取数据(对象写法)
//...mapState({he:'sum',xuexiao:'school'})
//借助mapState生成计算属性,从state中读取数据(数组写法),自定义计算属性名与state中对应属性名一致
...mapState(['sum','school']) ,
//借助mapGetters生成计算属性,从getters中读取数据(数组写法)
...mapGetters(['bigSum'])
}
methods:{
//借助mapMutations生成对应的方法方法中会调用commit去联系mutations
//...mapMutations({add:'ADD',subt:'SUBT'})
//数组写法
...mapMutations(['ADD','SUBT'])
//借助mapActions生成对应的方法方法中会调用dispatch去联系actions,传递的参数需要在事件触发时携带
...mapActions(['addOdd'])
}
03 - 优化示例
优化后,通过计算属性,模板中可以直接使用sum
,也可以直接调用store
中配置的函数(注意在绑定事件时传递参数),减少的代码量显而易见
methods: {
// add(){
// // this.sum += this.n
// // this.$store.dispatch("add",this.n)
// this.$store.commit("ADD",this.n)
// },
// subt(){
// // this.sum -= this.n
// // this.$store.dispatch("subt",this.n)
// this.$store.commit("SUBT",this.n)
// },
...mapMutations(["ADD","SUBT"]),
...mapActions(["addOdd","addWait"])
// addOdd(){
// // if(this.sum % 2){
// // this.sum += this.n
// // }
// this.$store.dispatch("addOdd",this.n)
// },
// addWait(){
// // setTimeout(() => {
// // this.sum += this.n
// // }, 1000);
// this.$store.dispatch("addWait",this.n)
// }
},
computed:{
...mapState(['sum']),
...mapGetters(['bigSum'])
}
Vuex模块化
为了让代码更好维护,让多种数据分类更加明确,我们可以选择将Vuex模块化。
01 - 修改store.js
注意开启命名空间,是为了解决不同模块命名冲突的问题,给每个模块配置namespaced:true
,之后在不同页面中引入getter、actions、mutations
时,需要加上所属的模块名
//求和相关配置
const countOptions = {
namespaced:true, //开启命名空间
actions:{
addOdd(context,value){
if(context.state.sum % 2){
context.commit('ADD',value)
}
},
addWait(context,value){
setTimeout(() => {
context.commit('ADD',value)
}, 1000);
}
},
mutations:{
ADD(state,value){
state.sum += value
},
SUBT(state,value){
state.sum -= value
}
},
state:{
sum:0
},
getters:{
bigSum(state){
return state.sum*10
}
}
}
//人员相关配置
const personOptions = {
namespaced:true, //开启命名空间
actions:{},
mutations:{
ADD_PERSON(state,person){
state.personList.unshift(person)
}
},
state:{
list:[
{id:'001',name:'张三'}
]
},
getters:{}
}
//创建并暴露(导出)store
export default new Vuex.Store({
modules:{
countOptions,
personOptions
}
})
02 - 开启命名空间后读取数据与调用函数方式
1、开启命名空间后,组件中读取state
数据
//方式一:自己直接读取
this.$store.getters['personOptions/firstPerson']
//方式二:借助mapGetters获取
...mapGetters('countOptions',['bigSum'])
3、开启命名空间后,组件中调用dispatch
//方式一:自己直接dispatch
this.$store.dispatch('personOptions/addPerson',person)
//方式二:借助mapActions
...mapActions('countOptions',["addOdd","addWait"])
4、开启命名空间后,组件中调用commit
//方式一:自己直接commit
this.$store.commit('personOptions/ADD_PERSON',person)
//方式二:借助mapMutations
...mapMutations('countOptions',["ADD","SUBT"]),
03 - 进一步模块化
可以将每组相关配置都放在单独的js
文件中,注意一定要导出,然后再在index.js
文件中引入