通过这篇文章让你彻底搞懂mapState、mapGetters、mapMutations、mapActions的使用
本文涉及知识点
- 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的获取与操作需要带上命名空间,操作相对会比较繁琐,使用映射方法可以简化我们的代码,用法如下:
PS: 只有设置了命名空间,映射方法才可以使用第一个参数
{
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个映射方法的使用,结果模块化与命名空间更能发挥它们的优势,实际开发中大家只要多尝试就能理解到它们折精髓。