Bootstrap

11.组件中调用Vuex的state,getters,mutations,actions,modules的数据传递、传参问题

博主为什么要总结标题的这些问题呢 

       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

 见下篇:13.Vuex模块中的命名空间namespaced

       总结以上知识点,只为方便以后自己查看,也希望能够帮助到正在看这篇博文的你,全凭自己总结的,可能会有部分错误,希望大家能够理解,也希望大家能够评论指出,谢谢大家。

附:Vue篇目录:

    1.Vue组件之间传值问题                              2.v-model 用在组件中

    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],欢迎哦^_^

 

;