stars-oceans / yhc

个人博客,我个人在学习,和开发中遇到的一些问题总结。
1 stars 0 forks source link

Vuex映射方法mapState、mapGetters、mapMutations、mapActions的使用 #15

Open stars-oceans opened 1 year ago

stars-oceans commented 1 year ago

本文涉及知识点

vuex Vuex模块化 namespace命名空间

4个映射方法(mapState、mapGetters、mapMutations、mapActions)的出现,使我们不必编写大量繁琐的代码去获取vuex中的数据,简化了用户操作,提高了开发者效率,接下来我们就来看看如何使用这4个方法

基本用法

假设Vuex的代码如下:

const store = new Vuex({
    state:{
        userInfo:{
            id:110,
            username:'laoxie'
        }
    },
    getters:{
        isLogin(state){
            return !!state.userInfo.id
        }
    },
    mutations:{
        login(state,payload){
            state.userInfo = payload
        },
        logout(state){
            state.userInfo = {}
        }
    },
    actions:{
        login(ctx,payload){
            ajax('/login',payload).then(data=>{
                ctx.commit('login',data)
            })
        }
    }
})

mapState与mapGetter映射的值都属于属性,所以一般用在computed选项中,mapMutations与mapActions映射的值都属于方法,所以一般用在methods中,它们的参数支持数组与对象用法,并返回一个对象

{
    computed:{
        // 把同名属性userInfo映射到computed中,以下两行代码等效
        // userInfo(){
        //        return this.$store.state.userInfo
          // }
        // 展开就是 跟上面一样了
        ...mapState(['userInfo']), 

        // 如需更改名字,则可使用对象形式(字符串或函数形式)
        ...mapState({user:'userInfo',currentUser:state=>state.userInfo})

        // mapGetters采用对象参数时不支持函数写法
        ...mapGetters(['isLogin']),
        ...mapGetters({logined:'isLogin'}),
    },
    methods:{
        // 以下两种写法等效于:logout(){this.$store.commit('logout')}
        ...mapMutations(['logout']), 
        ...mapActions({
            logout(commit,payload){
                // commit固定为第一个参数
                // payload为调用logout时传入的参数,不传则为undefined
                commit('logout')
            }
        }),

        // 以下两种写法等效于:login(user){this.$store.dispatch('login',user)}
        ...mapActions(['login']),
        ...mapActions({
            login(dispatch,payload){
                // dispatch固定为第一个参数
                // payload为调用login时传入的参数,不传则为undefined
                dispatch('login',payload)
            }
        })
    }
}

高级用法

假设Vuex使用了模块化及命名空间,更能体会4个映射方法的优势,假设vuex代码如下:

const user = {
    // 模块化并设置命名空间 
    namespaced:true,
    state:{
        userInfo:{
            id:110,
            username:'laoxie'
        }
    },
    getters:{
        isLogin(state){
            return !!state.userInfo.id
        }
    },
    mutations:{
        login(state,payload){
            state.userInfo = payload
        },
        logout(state){
            state.userInfo = {}
        }
    },
    actions:{
        login(ctx,payload){
            ajax('/login',payload).then(data=>{
                ctx.commit('login',data)
            })
        }
    }
}
const store = new Vuex({
    modules:{
        user
    }
})

Vuex模块化后,默认只影响state的获取,getters、mutations、actions依然在全局状态下,设置了命名空间(namespaced:true)后getters、mutations、actions的获取与操作需要带上命名空间,操作相对会比较繁琐,使用映射方法可以简化我们的代码,用法如下:

只有设置了命名空间,映射方法才可以使用第一个参数

{
    computed:{
        // 以下两个用法效果一至
        // 不用第一个参数用法如下
        ...mapState({userInfo:state=>state.user.userInfo}),
        // 设置第一个参数为模块名称
        ...mapState('user',['userInfo']), 

        // 以下两个用法效果一至
        ...mapGetters(['user/isLogin']), // 不推荐,给实例写入`user/isLogin`属性
        ...mapGetters('user',['isLogin']), // 给实例写入`isLogin`属性
    },
    methods:{
        // 以下写法等效于:logout(){this.$store.commit('user/logout')}
        ...mapActions('user',['logout']),

        // 以下写法等效于:login(user){this.$store.dispatch('user/login',user)}
        ...mapActions('user',{
            login(dispatch,payload){
                // dispatch固定为第一个参数
                // payload为调用login时传入的参数,不传则为undefined
                dispatch('login',payload)
            }
        })
    }
}

以上为mapState、mapGetters、mapMutations、mapActions 4个映射方法的使用,结果模块化与命名空间更能发挥它们的优势,实际开发中大家只要多尝试就能理解到它们折精髓。