一边学习vue3.x,一边实践,最近在做项目时,使用computed引入store中state的数据时,总是觉得很麻烦,想起新版兼容2.x,就想着引入mapState,可是怎么用都不对劲。后来,突然间醒悟过来,使用toRef或toRefs,就能实现mapState、mapGetters效果。
1、store.js
/*
* @Descripttion:
* @version: X3版本
* @Author:
* @Date: 2021-06-04 20:02:53
* @LastEditors:
* @LastEditTime: 2021-06-04 20:16:48
*/
import { createStore } from 'vuex'
export default createStore({
state: {
num:10,
str:'tom',
arr:[1,2,4],
obj:{
name:'jerry',
age:12
}
},
getters:{
getNum(state){
return state.num+2;
},
getObj(state){
return state.obj;
}
},
mutations: {
numMutation(state,data){
state.num=data;
},
strMutation(state,data){
state.str=data;
},
arrMutation(state,data){
state.arr=data;
},
objMutation(state,data){
state.obj=data;
},
},
actions: {
numAction({commit},args){
commit('numMutation',args)
console.log("numAction")
}
},
modules: {
}
})
2、App.vue
<template>
<h4>state.num:h4>
<span>{{ num }}span>
<button @click="numAction[0](120)">numActionbutton>
<br />
<h4>state.str:h4>
<span>{{ str }}span>
<button @click="strMutation[0]('张三')">strMutationbutton> <br />
<br />
<span
>state.arr:
<h4>{{ arr }}h4>span
>
<br />
<span
>state.obj:
<h4>{{ obj }}h4>span
>
<br />
<span
>state.getters.getNum:
<h4>{{ getNum }}h4>span
>
<br />
<span
>state.getters.getObj:
<h4>{{ getObj }}h4>span
>
<br />
template>
<script>
import { toRef, toRefs } from 'vue'
import { useStore } from 'vuex'
export default {
setup() {
const store = useStore();
//mapState
const { str, arr, obj } = toRefs(store.state);
const num = toRef(store.state, 'num');
//mapGetters
const { getNum, getObj } = toRefs(store.getters);
console.log('store:', store);
//mapMutations(toRefs也可以,这里就不举例了)
const strMutation = toRef(store._mutations, 'strMutation');
//mapActions
const numAction = toRef(store._actions, 'numAction');
return {
str,
num,
arr,
obj,
getNum,
getObj,
strMutation,
numAction
}
},
}
script>
<style scoped>
button {
width: 100px;
height: 30px;
margin-bottom: 20px;
}
style>
3、这里特殊说一下mapMutations和mapActions的替代方式
我们在生产环境下将store打印到控制台:
可以看到:commit、dispatch、getters、state等属性都不是以下划线开头的,根据我以往的经验,以下划线开头的属性,在生产环境下,很可能就拿不到了,因此我特意去生产环境测试了一下,依然可以拿到_mutations和_actions这两个属性,然后通过toRef或toRefs拿到其中的函数,其实拿到的是一个数组:
数组长度为一,数组内的元素实际就是我们想要的函数,因此才会出现: ,有个[0]
4、猜想:
感觉这个_mutations和_actions就是设计人员不想让我们使用,或者说不提倡我们使用,如果大家都这么用的话,那commit和dispatch就没必要存在了,我是觉得通过这种方式可以实现vue3.x环境下的mapMutations和mapActions,而且生产环境下也可以使用。希望后面vue的团队可以考虑下这方面吧(怎么在vue3.x实现mapMutations和mapActions),大家如果找到更好的方法,请@我,谢谢啦
5、后续:
之前是mapMutations和mapActions是通过toRef和toRefs实现的,后面想想觉得没必要,我们把数据用ref或者reactive封装一遍,是为了让数据具有响应性,能实现数据驱动视图。但是函数不需要,首先函数基本不会动态的改变,其次函数的调用相当于是引用传递,访问函数签名所在的地址,所以即使改变了,也会同步的。因此,根本不需要使用toRef或toRefs
代码如下:‘
<template>
<h4>state.num:</h4>
<span>{{ num }}</span>
<button @click="numAction(120)">numAction</button>
<br />
<h4>state.str:</h4>
<span>{{ str }}</span>
<button @click="strMutation('张三')">strMutation</button> <br />
<br />
<span
>state.arr:
<h4>{{ arr }}</h4></span
>
<br />
<span
>state.obj:
<h4>{{ obj }}</h4></span
>
<br />
<span
>state.getters.getNum:
<h4>{{ getNum }}</h4></span
>
<br />
<span
>state.getters.getObj:
<h4>{{ getObj }}</h4></span
>
<br />
</template>
<script>
import { toRef, toRefs } from 'vue'
import { useStore } from 'vuex'
export default {
setup() {
const store = useStore();
//mapState
const { str, arr, obj } = toRefs(store.state);
const num = toRef(store.state, 'num');
//mapGetters
const { getNum, getObj } = toRefs(store.getters);
console.log('store:', store);
//mapMutations
const { strMutation: [strMutation] } = store._mutations;
console.log(strMutation)
//mapActions
const { numAction: [numAction] } = store._actions;
return {
str,
num,
arr,
obj,
getNum,
getObj,
strMutation,
numAction
}
},
}
</script>
<style scoped>
button {
width: 100px;
height: 30px;
margin-bottom: 20px;
}
</style>
通过es6的解构功能,直接将mutation或者action中的函数解构出来,不必考虑响应性问题。
之所以会出现{ strMutation: [strMutation] }
这种形式,是为了避免前面说的[0]那种函数调用的形式,前面说了,直接结构出来是一个数组,这样美观程度上比较高。