Vue3在setup中使用Vuex的mapState&mapGetters

1,754 阅读1分钟

非原创,只是记录自己写代码而已!

  • 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;
};