非原创,只是记录自己写代码而已!
- vue 文件
<template>
<div>
{{count}} {{name}} {{doubCount}} {{oneName}}
<button @click="onAddCount">+</button>
<button @click="onSubCount({n:1})">-</button>
</div>
</template>
<script>
import useMapState from '../hooks/useMapState';
import useMapGetter from '../hooks/useMapGetter'
import { mapActions, mapMutations } from "vuex";
export default {
setup() {
// 不带命名空间的
// state
const mapStateObj = useMapState(['count', 'name'])
// getter
const mapGetterObj = useMapGetter(['doubCount'])
// 带命名空间的
const oneMapStateObj = useMapState('one',['oneName'])
const mutaionsFn = mapMutations({
onAddCount:'add'
})
const actionsFn = mapActions({
onSubCount: 'sub'
})
return {
...mapStateObj,
...mutaionsFn,
...actionsFn,
...mapGetterObj,
...oneMapStateObj
}
},
}
</script>
- store.js
import {createStore} from 'vuex'
const store = createStore({
state() {
return {
count: 0,
name: 'jyp'
}
},
getters: {
doubCount(state) {
return state.count * 2
}
},
mutations: {
add(state,playload) {
state.count += (playload.n || 1)
},
subtract(state, playload) {
state.count -= playload.n
}
},
actions: {
sub(context,playload) {
return new Promise((resolve) =>{
setTimeout(()=>{
console.log('sub')
context.commit('subtract',playload)
resolve(true)
},1000)
})
}
},
modules:{
one:{
namespaced: true,
state() {
return {
oneName: 'oneModule'
}
}
}
}
});
export default store
- useMapState 封装
import { computed } from "vue";
import { useStore, mapState, createNamespacedHelpers } from "vuex";
export default (nameSpace,mapper) => {
let mapObj = null;
const computedObj = {};
const currentStore = useStore();
if(nameSpace && typeof nameSpace === 'string') {
mapObj = createNamespacedHelpers(nameSpace).mapState(mapper)
}else {
mapper = nameSpace;
// mapState 返回的是一个 对象,值是 Fn
/*
{count:Fn,name:Fn}
*/
mapObj = mapState(mapper);
}
Object.keys(mapObj).forEach(key =>{
// 核心是 通过 bind 将 this 指向 store
computedObj[key] = computed(mapObj[key].bind({$store: currentStore}))
})
return computedObj
}
- useMapGetter 思路和上面 useMapState 是一样的
import { computed } from 'vue';
import { useStore, mapGetters, createNamespacedHelpers } from 'vuex';
export default (nameSpace, mapper) => {
let mapObj = null;
const computedObj = {};
const currentStore = useStore();
if (nameSpace && typeof nameSpace === 'string') {
mapObj = createNamespacedHelpers(nameSpace).mapGetters(mapper);
} else {
mapper = nameSpace;
mapObj = mapGetters(mapper);
}
Object.keys(mapObj).forEach((key) => {
computedObj[key] = computed(mapObj[key].bind({ $store: currentStore }));
});
return computedObj;
};