vue3中对mapState进行简易的封装

1,007 阅读1分钟

1.vue2中获取vuex中数据的方式

<template>
  <div>
    <h2>{{ $store.state.counter }}</h2>
    <h2>{{ sCounter }}</h2>
    <h2>{{ sName }}</h2>
  </div>
</template>

<script>
  import { mapState } from 'vuex'
  
  export default {
    computed: {
      // 方式1: 传入数组对象
      // ...mapState(["counter", "name", "age", "height"])
      // 方式2: 传入函数对象
      ...mapState({
        sCounter: state => state.counter,
        sName: state => state.name
      })
    }
  }
</script>

2.vue3中获取vuex中数据的方式

<template>
  <div>
    <h2>{{ $store.state.counter }}</h2>
    <h2>{{ $store.state.name }}</h2>
    <h2>{{ sCounter }}</h2>
    <h2>{{ sName }}</h2>
  </div>
</template>

<script>
import { useStore } from "vuex";
import { computed } from "vue";

export default {
  setup() {
    const store = useStore();
    const sCounter = computed(() => store.state.counter);
    const sName = computed(() => store.state.name);
    return {
      sCounter,
      sName,
    };
  },中
};
</script>

3.对比vue2中在mapState中传入函数对象

通过 ...mapState({() => {}}) 的方式不难看出此方法返回的是一个个的函数对象,而在vue3中使用vuex的方式是在computed包住一个回调函数,细心地同学可以看出这和vue2中使用mapState时包裹的函数是否有些相似?带着这个疑问,咋们可以试一试能否通过遍历的方式拿到mapState的返回值,再循环这个返回值将其包裹在computed函数中去。

<template>
  <div>
    <h2>{{ $store.state.counter }}</h2>
    <h2>{{ $store.state.name }}</h2>
    <h2>{{ counter }}</h2>
    <h2>{{ name }}</h2>
  </div>
</template>

<script>
import { mapState, useStore } from "vuex";
import { computed } from "vue";

export default {
  setup() {
    const store = useStore();
    const storeStateFns = mapState(["counter", "name"]);
    const storeState = {};
    Object.keys(storeStateFns).forEach((fnKey) => {
      console.log(storeStateFns[fnKey]);
      // 在此不使用bind会报错:read properties of undefined (reading '$store')所以在此需要手动为该方法绑定this
      const fn = storeStateFns[fnKey].bind({ $store: store });
      storeState[fnKey] = computed(fn);
    });
    return {
      ...storeState,
    };
  },
};
</script>

在此时就可以看到一个简单的雏形啦,不用每次获取vuex中的一个数据就又去写一次computed函数。接下来的任务便是将其封装为一个工具函数便可。

4.封装成为一个工具函数

import { computed } from 'vue'
import { mapState, useStore } from 'vuex'

export function useState(mapper) {
  // 拿到store
  const store = useStore()

  // 获取到对应的对象的functions
  const storeStateFns = mapState(mapper)

  // 对数据进行转换
  const storeState = {}
  Object.keys(storeStateFns).forEach(fnKey => {
    const fn = storeStateFns[fnKey].bind({$store: store})
    storeState[fnKey] = computed(fn)
  })
  return storeState
}

在vue3中的使用方法就变得和使用mapState非常的类似了

setup() {
  const storeState = useState(["counter", "name"])
  return {
    ...storeState
  }
}

5.总结

到此一个简单的useState hooks就基本实现了,还可以封装一个useGetters hooks,再者可以将这个hooks封装成为兼容modules中获取state的写法。