天天看点

10.Vuex组件中的mapState、mapGetters、mapMutations、mapActions等辅助函数

State

1.state中的数据,组件中如何获取

 this.$store.state.xxx属性
           

2.mapState辅助函数        

1.引入mapState
    import {mapState} from 'vuex'
2.在computed计算属性中使用
    export default{
        computed:mapState(
            ['count']
        )
      }
           

3.计算属性,使用了mapState作为辅助函数,其他计算属性怎么写?

//mapState 函数返回的是一个对象
//ES6  对象展开运算符...mapState(['count'])
export default{
    computed:{
        ...mapState(['count']),//一起使用时,ES6使用对象展开运算符此对象混入到外部对象中
        message(){//其他计算属性
            return xxxx;
        }
    }
}
           

Getter

1.store.js中的getters,组件中如何获取?

this.$store.getters.xxxx(getters名称)
           

2.store.js中的getters,如何接收多个参数?

//state作为第一个参数接收,(id,name)作为其他两个参数接收,也可以接收一个对象
getters:{
    increMethod:(state)=>(id,name)=>{
        console.log(id)
        if(id<1){
            if(name === 'lucy'){
                return state.count ++;
            }else{
                return 'not lucy';
            }
        }else{
            return 88;
        }
    }
}  

//在组件中使用
export default({
    computed:{
        xxx(){
            return this.$store.getters.increMethod(0,'ll');  //这么加参数
        }
    }
})

//辅助函数mapGetters加参数
待继续研究
           

3.mapGetters辅助函数

1.引入mapGetters
    import {mapGetters} from 'vuex'
2.其他操作与mapState辅助属性类似,此处不再过多描述
           

4.计算属性,使用了mapGetters作为辅助函数,其他计算属性怎么写

       与mapState辅助属性类似,此处也不再过多描述

Mutations

1.store.js中的mutations,组件中如何执行?

//1.普通执行
this.$store.commit('xxx');//xxx指mutations名称
//2.如果有对象形式的参数时(此处对应下面2中mutaions接收对象情况使用)
this.$store.commit({
    type:'increment',
    num:10
})
           

2.在store.js中编写mutations,可以接收多个参数,也可以接收对象

//接收多个参数
mutations:{
    increment(state,n){
        state.count += n;
    }
}
//接收对象
mutations:{
    increment(state,obj){
        state.count += obj.num;
    }
}
           

3.使用常量替代 Mutation 事件类型

      1.为什么要用常量替代Mutation事件?

                可以将所有的Mutation事件,写入到一个单独的文件中,然后通过常量来替代,可以方便开发者对项目中所有Mutation

         事件一目了然

     2.如何使用常量来替代?

1.创建一个单独文件mutation_type.js
2.在js中定义常量信息
  export const SOME_MUTATION = 'SOME_MUTATION'
3.在store.js中,通过import引入
  import {SOME_MUTATION} from './mutation_type.js'
4.常量在mutations中如何使用
  mutations:{
      [SOME_MUTATION] (state){
          //这就是使用常量替代Mutation
      }
  }
           

4.如何在组件中执行Mutation方法(mapMutations辅助函数的使用)

1.普通执行
    this.$store.commit('xxx')提交
2.使用mapMutations辅助函数
    1.引入mapMutations
        import {mapMutations} from 'vuex'
    2.在methods方法中使用
        export default({
            methods:{
                ...mapMutations:(
                    ['increment']
                )
            }
        })
           

5.在组件中执行Mutations,能否对mutations的名称进行修改(设置别名)?

       store.js中定义的名称为add的mutation方法,但是在组件中,我已经在methods中定义了一个名称为add的方法,这时候就需要用到mapMutations辅助函数来设置一个别名了

//store.js
export default new Vuex.Store({
    mutations:{//mutations中定义了一个add方法
        add:(state)=>{
            state.count ++;
        }
    }
})
//组件中
export default({
    methods:{
        add(){...},//组件中,已经存在名称为add的方法
        ...mapMutations({
            increment:'add'//故使用辅助函数,将该方法别名为increment,然后通过increment访问即可,其实就是在访问store.js中的名称为add的mutations方法
        })
    }	
})
//在组件中如何使用呢?
<button @click="increment">mapMutations++</button>
           

6.store.js中的mutations有多个参数,使用辅助函数能否实现多个参数传递??

//mapMutations辅助函数,也可以传递参数,目前我发现只能传递一个参数,多个参数建议传递一个对象。有待继续研究
//store.js
export default new Vuex.Store({
    mutations:{
        increment:(state,obj)=>{
            console.log(obj.n)
            console.log(obj.name)
            if(obj.name == 'liu'){
                state.count+=obj.n;
            }else{
                state.count ++;
            }
        }
    }
})
//组件中
export default({
    methods:{//二选一
        //1.不改别名类型的(此处看不到任何参数信息)
        ...mapMutations(['increment'])
        //2.可以改别名的(此处看不到任何参数信息)
        ...mapMutations({
            add:'increment'   
        })
    }	
})
//组件中如何使用呢(直接在后面加参数即可,此处是一个对象参数)
<button @click="increment({n:8,name:'liu'})">mapMutations++++</button>
或者
<button @click="add({n:8,name:'liu'})">mapMutations++++</button>
           

7.mutations中执行的都是同步事务操作

     最好不要再mutations中执行异步操作。如果异步操作数据了,组件在commit 后,数据不能立即改变,而且不知道什么时候会改变。处理异步操作,可在一下的actions中进行。

Actions

1.actions和mutations有什么区别?

   ①Action 提交的是 mutation,而不是直接变更状态。

   ②Action 可以包含任意异步操作。

2.store.js中,actions如何编写?

//store.js中,编写一个名称为incrementAction的action
export default new Vuex.Store({
    actions:{
        incrementAction(context){
            context.commit('increment')
        }
    }
})
//简化代码:我们可以使用ES6参数解构来简化代码(特别是我们需要调用 commit 很多次的时候)
export default new Vuex.Store({
    actions:{
        incrementAction( {commit}){
            commit('increment')
    }
}
           

3.组件中,actions如何来分发mutations?

//有两种方式
1.普通分发
    this.$store.dispatch('xxx',{amout:10})   
2.对象方式分发
    this.$store.dispatch({
        type:'xxx',
        amount:10
    })
           

4.使用mapActions辅助函数,来分发mutations

   mapActions辅助函数的使用方法,与mapMutations类似,即①可以修改名称②可以接收参数信息。可以参考mapMutations

5.组合actions的使用

        Action 通常是异步的,那么如何知道 action 什么时候结束呢?更重要的是,我们如何才能组合多个 action,以处理更加复杂的异步流程?

   ①Promise实现

       Promise是一种异步方案它有3种状态:Pending(进行中)、Resolved(已完成)、Rejected(已失败)。

//使用Promise实现的关闭定时器方案:
export default new Vuex.Store({
    actions:{
        actionA({state,commit}){
            let id = null;
            // 异步操作
            // 只要调用 resolve(),就会立马调用 then()
            const promise = new Promise((resolve,reject)=>{
                id = setInterval(()=>{
                    commit('increment',{n:22,name:'liu'});
                    if(state.count>100) resolve(state.count);   //会跳到then()
                    if(state.count==99) reject(state.count);  //会跳到catch(error)
                },1000);
            });
            promise.then((value)=>{//then()部分
                console.log(id);
                clearInterval(id);
            }).catch((error)=>{//异常处理部分
                console.log('fail',error)
            })
        }
    }
})


//Promise 还能这么写
new Promise((resolve, reject) =>{
    setTimeout(()=>{
        //resolve('Hello Vue');
        reject('Hello Error');
    },1000)
}).then(data =>{
    console.log(data);
}, error =>{
    console.log("error");
})
           

   ②在组件中,可以这么来使用组合action(可能还有更好的写法,有待研究)

export default({
    methods:{
        multiAction(){//使用组合action
            this.$store.dispatch('actionB').then(()=>{
                if(this.count>100){
                this.$store.dispatch('actionC').then(()=>{
                    alert("完毕")
                })
            }
        })
    }
})
           

   ③在store.js中,使用组合action

export default new Vuex.Store({
    actions:{
        actionD({state,commit,dispatch}){
            let id ;
            const promise = new Promise((resolve,reject)=>{
                id = setInterval(()=>{
                    commit('increment',{n:28,name:'liu'});
                        console.log(state.count);
                    if(state.count>100){
                        resolve(state.count);
                    }
                },1000)
            });
            promise.then((value)=>{
                clearInterval(id)
                dispatch('actionC');//或者commit('其他的mutations')
                console.log("完毕")
            })
        }
    }
})
           

   ④使用async/await,组合action

      async/await还在进一步了解中,有点疑问,后续会补的

      参考:https://vuex.vuejs.org/zh/guide/actions.html

Module

1.如何将单一store.js拆分成多个模块?

        由于使用单一状态树,应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂时,store 对象就有可能变得相当臃肿。

        为了解决以上问题,Vuex 允许我们将 store 分割成模块(module)。每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块——从上至下进行同样方式的分割:

//切记:子模块是这么定义的,而不是const moduleA = new Vuex.Store({...})
const moduleA = {
  state: { ... },
  mutations: { ... },
  actions: { ... },
  getters: { ... }
}

const moduleB = {
  state: { ... },
  mutations: { ... },
  actions: { ... }
}

const store = new Vuex.Store({
  modules: {
    a: moduleA,
    b: moduleB
  }
})

store.state.a // -> moduleA 的状态
store.state.b // -> moduleB 的状态
           

2.在模块moduleA/moduleB中,如何获取兄弟节点module/根节点store中的一些属性?

const moduleA ={
    actions:{
        moduleAAction({state,commit,rootState}){
            //state---->为子节点状态,即当前moduleA
            //rootState--->即父模块状态,即store
            //通过state.count--->来获取模块中的state变量
            //通过rootState.count--->来获取父模块中的state变量
            console.log('moduleA模块中的count属性值:'+state.count);
            console.log('父模块中的hello属性值:'+rootState.hello);
            console.log('兄弟模块moduleB中的count属性:'+rootState.moduleB.count);
            commit('moduleAIncr');
        }
    }
}
           

3.命名空间

        默认情况下,模块内部的 action、mutation 和 getter 是注册在全局命名空间的,这样使得多个模块能够对同一 mutation 或 action 作出响应。

        如果希望你的模块具有更高的封装度和复用性,你可以通过添加 namespaced:true 的方式使其成为带命名空间的模块。当模块被注册后,它的所有 getter、action 及 mutation 都会自动根据模块注册的路径调整命名

附: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的使用