博主为什么要总结标题的这些问题呢
1. 因为在之前Vue 2.0之前,面对小型前端单页面富应用(SPA)应用,都是使用localStorage等一些缓存等简单的方式来解决数据之间的传输问题。面对相对大型的应用,使用上述localStorage等简单方法已经无法满足需求,所以需要使用到Vuex,可以更加方便的知晓页面之间具体的流向问题。
2.在学习到Vuex时,简单看传值问题,发现也没有多难,就是一些简单的commit,dispatch等。但是在分模块之后,面对模块之间的数据之间相互传递,以及在组件中调用mutaions,actions等方法时,如何传参问题。一时感觉问题好多。脑子里满是晕乎,于是乎,经过不懈的努力,写了这样一篇博文。
3.以下内容,纯手工练习,方便大家的查看,总结完也方便自己日后查看。如有问题,欢迎大家评论指出,然后我来改正。如有错误,望轻喷,谢谢
实例说明:
Vuex中,根Store.js,分为如下五个模块:
Module:分为两个模块:moduleA和moduleB
State:Store.js中包含一个属性:count,模块中有两个属性:countA和countB
Getters:模块A中有moduleAGetter,模块B中有moduleBGetter
Mutations:模块A中有moduleAMutations,模块B中有moduleBMutations
Actions:模块A中有moduleAActions,模块B中有moduleBActions
如下1-4所有情况,仅仅在Module层不使用命名空间的前提下满足!!!
是否使用命名空间,可在模块中,使用namespaced:true来开启。如要查看命名空间相关知识,请查看该博文5.Module部分知识
1.State
个人观点:state中的数据,Vuex规定只能通过mutations来进行提交操作,基本在组件中,调取相关mutations、actions等就能满足要求,所以,个人觉得state在组件中读取没有特殊情况下的话,也没多大意义。
<!-- moduleA--模块A -->
const moduleA = {
state:{
count:888
}
}
<!-- 组件中,获取State的数据 -->
<template>
<div>
<span>基础获取方式:(通过该方式获取的,可以写在computed计算属性内,这样看着不复杂)</span>
<span>获取父store中的state下的count值:{{$store.state.count}}</span>
<span>获取moduleA模块中的state下的count值:{{$store.state.moduleA.count}}</span>
<hr>
<span>mapState辅助函数获取方式:</span>
<span>获取父store中的state下的count值:{{count}}</span>
<span>获取moduleA模块中的state下的count值:{{countA}}</span>
</div>
</template>
<script>
import {mapState} from 'vuex';
export default {
name: "Body",
computed: {
//获取父store中的state下的count值
...mapState(['count']),
//获取moduleA模块中的state下的count值
...mapState({
countA:state=>state.moduleA.countA
}),
}
}
</script>
2.Getters
rootState和 rootGetters参数顺序不要写反,一定是state在前,getter在后面,这是vuex的默认参数传递顺序。
rootGetters参数中,包括根store以及模块中的所有getters方法,直接rootGetters.方法名即可获取到。
有这样的一个场景: Vuex 定义了某个数据 list, 它是一个数组,如果只想得到小于 10 的数据,最容易想到的方法可能是在组件的计算属性里进行过滤。这样写完全没有问题。但如果还有其他的组件也需要过滤后的数据时,就得把 computed 的代 码完全复制一份,而且需要修改过滤方法时,每个用到的组件都得修改,这明显不是我们期望的结 果。如果能将 computed的方法也提取出来就方便多了, getters 就是来做这件事的。
个人观点:针对以上这个场景,getters其实就相当于是一个普通方法。getters和mutations/actions之间其实没有任何关系,所以说,在此处getters只要能获取到根store或者兄弟模块的state参数值,getters方法,它的目标其实就已经达到了
//模块中
const moduleA = {
getters:{
showStateData(state,getters,rootState,rootGetters){
console.log('当前模块的count值:'+state.countA);
console.log('根store中的count值:'+rootState.count);
console.log('兄弟模块moduleB中的countB值:'+rootState.moduleB.countB);
console.log('根store中的名为increNum的getters方法:'+rootGetters.increNum);
console.log('兄弟模块moduleB中的名为moduleBGetter的getters方法:'+rootGetters.moduleBGetter);
},
======================================================================================================
//就是此处。该getters针对下面组件中有参数的情况
moduleAGetter:(state)=>(param,name)=>{
console.log(param)
console.log(name)
}
//等价于
moduleAGetter(state) {
return function (param,name){
console.log(param);
console.log(name);
}
}
}
}
//组件中使用时,如何传参问题
<template>
<div>
我是Body<hr>
<button @click="moduleAGetter">getters获取数据</button>
<button @click="changeNameGetter">更名后的getters获取数据</button>
</div>
</template>
<script>
import {mapGetters} from 'vuex';
export default {
name: "Body",
methods: {
//1.普通情况下,分为如下两种情况:
commonGetter(){
//⑴无参数引用getter
return this.$store.getters.moduleAGetter;
//⑵有参数引用getter,该这么传(亦可传递对象)。或者这样子传也好:commonGetter(id,name){...}
return this.$store.getters.moduleAGetter(996,'Mr.Liu');//请查看上面模块中定义的moduleAGetter方法。
},
//2.mapGetters辅助函数,分为如下三种情况:
//⑴无参数引用getter
...mapGetters(['moduleAGetter']),
//⑵无参数引用getter,更名情况下
...mapGetters({
changeNameGetter:'moduleAGetter'
}),
//⑶有参数引用getter
//暂未找到mapGetter如何使用辅助函数传参情况,如有知道,欢迎大家补充
}
}
</script>
3.Mutations
mutations,唯一的用途就是:用来修改state中的数据。他不可能去拿根store或者兄弟模块的getters,mutations,actions等。
个人观点:mutaions只能修改state中的数据,况且应该是只能修改本模块的state中的数据,所以它是无法拿到根store和兄弟模块的state的值,只能拿到自己模块的state值
如果使用 mutations 修改 state 中的对象中的属性,比如 obj {id:1,name:'Mary'},修改对象已有属性,会响应式显示。如果修改的属性对象中没有,比如 state.obj['address']='LA'修改时,这样操作并不是响应式的。需要通过 Vue.set(state.obj,'address','LA') 这种方式才是响应式的。
使用 delete state.obj.address 删除某个对象属性时,也不是响应式的。需要通过 Vue.delete(state.obj,'address') 这种方式删除才是响应式的。
//模块中
const moduleA = {
mutations:{
moduleAMutation(state){
console.log('当前模块的count值:'+state.count);
},
// 使用其他写法时(在下文methods中由介绍其他写法),接收参数有所不同(此处定义名为count,拿到的并不是 5,而是一个对象)
// Mutations中的参数被称为是 mutation 的载荷(Payload)
// moduleAMutation(state, count){
// console.log('当前模块的count值:'+state.count);
// }
// 此处推荐这么定义
// moduleAMutation(state, payload){
// //此处 payload 接收的是一个{ type: 'moduleAMutation', count: 5} 的对象
//}
=======================================================================================================
//paramMutation针对下面组件中传参情况下使用
paramMutation(state,obj){
console.log(obj.id);
console.log(obj.name);
console.log('A模块中的count属性值:'+state.count);
},
}
}
<!--组件中使用时,如何传参问题-->
<!--目前个人研究完,模块中的mutaion中,默认第一个传递参数是state,这个是Vuex定死的的,剩下的自定义参数部分-->
<!--个人研究发现我们只能传递一个。如果要传递多个参数,只能以对象的形式传递。如有错误或者指正,欢迎评论修改-->
<template>
<div>
我是Body<hr>
<button @click="commonMutation">⑴基础mutations获取数据</button>
<button @click="moduleAMutation">⑵辅助函数mutations获取数据</button>
<button @click="changeNameMutation">⑶改名mutations获取数据</button>
<button @click="paramMutation({id:996,name:'Mr.Liu'})">⑷有参数普通mutations获取数据</button>
<button @click="paramMapMutation({id:996,name:'Mr.Liu'})">⑸有参数辅助函数mutations获取数据</button>
</div>
</template>
<script>
import {mapGetters,mapActions,mapMutations} from 'vuex';
export default {
name: "Body",
methods: {
⑴commonMutation(){
this.$store.commit('moduleAMutation');
},
⑵...mapMutations(['moduleAMutation']),
⑶...mapMutations({
changeNameMutation:'moduleAMutation'
}),
⑷paramMutation(obj){
this.$store.commit('moduleAMutation',obj);
},
⑸...mapMutations(obj){//传参,使用辅助函数,参数目前我研究完,只能传递到上面<button @click="paramMapMutation({id:996,name:'Mr.Liu'})"><button>调用的地方
paramMapMutation:'moduleAMutation',
})
// Mutations 使用 commit 进行提交,还有另外一种风格,如下:
// 其他风格写法:
// 还可以像下面这样写(但是在定义mutations方法的地方,接收参数有点区别,看上面)
// this.$store.commit({
// type: 'moduleAMutation',
// count: 5 //参数
// })
}
}
</script>
<style scoped>
</style>
4.Actions
Actions主要用来①提交mutations ②执行异步操作
Vuex为Actions提供rootState参数,来获取根store,兄弟模块中的数据。
个人观点:既然已经分模块,各个模块数据之间要相互独立,所以模块A中的actions也不可能去提交模块B或者跟store中的mutations吧,所以actions部分,只能获取到根store或者兄弟模块中的state数据即可
//模块中
const moduleA = {
actions:{
getStateData({state,commit,getters,rootState,rootGetters}){
console.log('当前模块的count值:'+state.count);
console.log('根store中的count值:'+rootState.count);
console.log('兄弟模块moduleB中的count值:'+rootState.moduleB.count);
rootGetters.increment();//获取根store中的名为increment的getters方法
getters.moduleAIncrement();//获取当前模块中的getters方法,传参的话直接在括号中传即可,可以使多个参数,也可以是一个obj对象
},
=======================================================================================================
//moduleAAction针对下面组件中传参情况下使用
moduleAAction({state,commit,rootState},obj){//此处传递了一个obj对象参数
console.log(state)
console.log(obj.id);
console.log(obj.name);
console.log('A模块中的count属性值:'+state.count);
console.log('父模块中的count属性值:'+rootState.count);
console.log('兄弟模块moduleB中的count属性:'+rootState.moduleB.count);
commit('moduleAIncr',obj.id);//此处为将obj对象的id参数,继续提交mutaions使用
},
//!!!重点:Vue 不推荐actions中直接对state的数据操作。推荐通过mutations来修改 state 中的数据()
demoAction(context,payload){// 此处payload是一个对象参数,类似obj对象(mutations中,参数被称为是载荷(Payload),所以此处也定义payload,舍弃很low的 obj定义)
context.commit('mutations的名称');//context为上下文的意思
}
// ES6:对象的解构赋值
//提示:这种直接写个 context 参数亦可。
//上面这样的方式moduleAAction({state,commit,rootState}) 等这种参数方式,是ES6中对象的解构赋值(相当于就是 context 中的一个个对象,直接放到哪里,省去了编写 context.state、context.commit 等多个这样的代码)
},
mutations:{
//此处额外附名为moduleAIncr的mutations方法,仅用作下面部分参考使用
moduleAIncr:(state,num)=>{
console.log(num);
state.count +=num;
console.log(state.count)
}
}
}
<!--组件中使用时,如何传参问题(其实和上面的Mutations传参一样,没有区别)-->
<template>
<div>
我是Body<hr>
<hr>
<button @click="commonAction">⑴基础actions获取数据</button>
<button @click="moduleAAction">⑵辅助函数actions获取数据</button>
<button @click="changeNameAction">⑶改名actions获取数据</button>
<button @click="paramAction({id:996,name:'Mr.Liu'})">⑷有参数普通actions获取数据</button>
<button @click="paramMapAction({id:996,name:'Mr.Liu'})">⑸有参数辅助函数actions获取数据</button>
</div>
</template>
<script>
import {mapGetters,mapActions,mapMutations} from 'vuex';
export default {
name: "Body",
methods: {
⑴commonAction(){
this.$store.dispatch('moduleAAction')
},
⑵...mapActions(['moduleAAction']),
⑶...mapActions({
changeNameAction:'moduleAAction'
}),
⑷paramAction(id,name){
this.$store.dispatch('moduleAAction',id,name);
},
⑸...mapActions({//传参,使用辅助函数,参数目前我研究完,只能传递到上面<button @click="paramMapAction({id:996,name:'Mr.Liu'})"><button>调用的地方
paramMapAction:'moduleAAction'
})
}
}
</script>
<style scoped>
</style>
5.Modules
总结以上知识点,只为方便以后自己查看,也希望能够帮助到正在看这篇博文的你,全凭自己总结的,可能会有部分错误,希望大家能够理解,也希望大家能够评论指出,谢谢大家。
附:Vue篇目录:
3.Vue.js 实战 调查问卷WebApp项目 4.vue-cli + webpack搭建Vue开发环境
5. Vue简单问题汇总(持续更新...) 6.Vue组件之间数据通信之Bus总线
7.Vue-Router导航钩子(附Demo实例) 8.ES6箭头函数与普通函数的区别
9.Vuex的使用 10.Vuex组件中的mapState、mapGetters、mapMutations、mapActions等辅助函数
11.组件中调用Vuex的state,getters,mutations,actions,modules的数据传递、传参问题
12.Vuex命名空间namespaced 13.Vue axios的使用
---->如有疑问,请发表评论,或者联系博主:[email protected],欢迎哦^_^