Vue3(Vuex 4.x)的setup中使用mapState

1,488 阅读1分钟

Vue3(Vuex 4.x)中useState的封装

在使用vuex的时候,我们经常会想把store中state中的数据结构到组件中方便直接使用,而不是通过store.state.xxx去访问,但是随着vue的更新,在vue3CompositionApi中的setup中,无法直接通过this.store.state.xxx去访问,但是随着vue的更新,在vue3的Composition Api中的setup中,无法直接通过this.store访问,所以我们会想去通过一些手段去使得mapState也像在vuex 3.x中一样使用

废话少说直接上代码

封装useState (/src/hooks/useState.js)

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


/**
 * @param {Array || Object} mapper 
 * @returns {Array} storeState
 */
export function useState(mapper) {
  // vue3的setup中没有绑定this(无法通过this.$store获取到),通过useStore获取store对象
  const store = useStore()

  // mapState返回的是一系列的function:{name:nameFn,age:ageFn}的对象
  const storeStateFns = mapState(mapper)

  // 对数据进行转换

  // 存放最终可以在模板上使用的数据 {{ name }}
  const storeState = []
  // 在组件中使用vuex store中的数据,应该将mapState返回的数据存放到computed中
  Object.keys(storeStateFns).forEach(fnKey => {
    // mapState中获取到的每一个函数内部其实都是通过this.$store.state.name····进行访问的,但是在setup中并没有this.$store,所以通过bind将store对象绑定到每一个mapState中的函数中
    const fn = storeStateFns[fnKey].bind({ $store: store })
    // 将获取到的所有state存放到storeState中
    storeState[fnKey] = computed(fn)
  })

  return storeState
}

有一定的封装复之后,在组件中就可以直接使用useState来代替mapState了

<template>
  <div>
    <h4>封装setup中使用mapState</h4>
    {{name}}-{{age}}-{{height}}
    <hr>
    {{sName}}-{{sAge}}
  </div>
</template>

<script>
  import {useState} from '../hooks/useState'
  export default {
    setup() {
      const storeState = useState(['name','age','height'])
      const storeState2 = useState({
        sName:state=> state.name,
        sAge:state=>state.age
      })
      return {
        ...storeState,...storeState2
      }
    }
  }
</script>

<style lang="scss" scoped>

</style>