Vuex进阶

643 阅读2分钟
vuex的模块化:单一状态树,应用内的所有数据都会集中到一个比较大的store对象上,当应用规模较大时store对象就会变的十分臃肿;为了解决这个问题vuex允许我们将store进行模块分割;每个模块都拥有自己的store/mutations/actions/getters

开发过程中通常采用的模块化有两种方案;
一是按照功能模块化(即state/ mutations/ actions/ getters)各一个文件,
二是根据业务逻辑模块化(即按照应用功能划分,每一个都有独立的state/ mutations/ getters/ actions) 

state

模块内的state对象是局部状态

const state = {
    count:11
} //moduleA.js

组件内调用:
this.$store.state.moduleA.name 调用局部状态中的数据

getter

和state不同,getter /mutation/action在默认情况下是注册在全局命名空间的,只有当该模块开启命名空间(namespaced: true)时getter才是局部getter

const getters = {
    someGetters(state, getters, rootState, rootGetters){
         return state.name   
    }
}

参数:
state      : 当前模块状态
getters    : 全局getter(默认) / 局部getter(开启命名空间后)
rootState  : 根状态(开启命名空间后出现)
rootGetters: 全局getter(开启命名空间后出现)
当模块启用命名空间时,rootState和rootGetters会作为第3/4参数传入,通过它们可以调用根状态上的数据和根getter

组件内调用:


默认(未开启命名空间):
this.$store.getters['name']        //全局内的getter(无局部)

启用命名空间后:
this.$store.getters['name']        //全局getter
this.$store.getters['module/name'] //某个模块内getter

mutations

它的参数只有state和payload, state也只是当前模块的状态;因此其内部
不可以访问根state&其他模块中的getters/mutations/actions

const mutations = {
    someMutations(state, payload){
        commit('someOtherMutations')
    }
}

组件内调用:
默认(未开启命名空间):
this.$store.commit('type', payload)            //全局内的mutation(无局部)

启用命名空间后:
this.$store.commit('module/type')                //某个模块内的mutation
this.$store.commit('type', payload, {root:true}) //全局mutation

actions

const actions = {
    someActions({state, rootState, commit, dispatch, getters, rootGetters}, payload){
        参数: context & payload    
        state      : 局部状态
        rootState  : 根状态(启动命名空间后出现)
        commit
        dispatch
        getters     : 本模块的getter
        rootGetters : 根getter(启动命名空间后出现)
         	dispatch('someOtherAction') // ->本模块内moduleA/someOtherAction
    }
}

组件内调用:
默认(未开启命名空间)
this.$store.dispatch('someOtherAction', payload)  //全局(无局部)

启用命名空间后:
this.$store.dispatch('module/someOtherAction', payload)       //某模块内的someOtherAction
this.$store.dispatch('someOtherAction', payload, {root:true}) //全局内的someOtherAction

在带有命名空间的模块内注册全局action

若需要在带命名空间的模块注册全局 action,你可添加 root: true,并将这个 action 的定义放在函数 handler


export default = {
    namespaced: true,

    actions:{
        gloable_action :{
            root:true,
            handler(namespacedContext, payload){
                ...
            }//此时的gloable_action 就是全局的action
        }
    }
}


带命名空间的模块内使用辅助函数

模块化后组件内各属性的调用相比之前更加繁琐,也更容易出错;辅助函数显得更加方便

import {mapState, mapGetters, mapMutations, mapActions} from 'vuex'

为了更加方便的书写,辅助函数允许我们将模块命名字符转作为第一个参数传递,它会自动帮我们绑定到需要的地方
同样的,需要改变映射命名的就用对象的形式,否则更推荐数组(注意数组要用'')


组件内:
computed:{
    ...mapState('moduleA',{
         newName : state => state.name,
         newAge  : state => state.age,  
    }),

    ...mapGetters('moduleA', [
        'someGetters',
        'someOtherGetters'
    ])
},

methods:{
    ...mapMutations('moduleA',[
       'someMutation',
       'someOtherMutations'
    ]),

    ...mapActions('moduleA',{
        newActions      : 'someActions',
        newOtherActions : 'someOtherActions'
    })

}