在 Vue3 中使用 Vuex 时,由于 Composition API 的引入,映射 state
和 getters
的方式与 Vue2 的 Options API 有所不同。以下是具体实现方式:
1. 基础方式:手动映射(推荐)
在 Vue3 的 <script setup>
中,通过 useStore
获取 store 实例,再结合 computed
手动映射 state
和 getters
:
<template><div><p>当前计数:{{ count }}</p><p>加倍后:{{ doubleCount }}</p></div>
</template><script setup>
import { useStore } from 'vuex'
import { computed } from 'vue'// 获取 store 实例
const store = useStore()// 映射 state(通过 computed 保持响应式)
const count = computed(() => store.state.count)// 映射 getters
const doubleCount = computed(() => store.getters.doubleCount)
</script>
2. 封装工具函数:模拟 Vue2 的 map 辅助函数
如果习惯 Vue2 中的 mapState
、mapGetters
,可以封装一个工具函数实现类似功能:
// store/mappers.js
import { computed } from 'vue'
import { useStore } from 'vuex'// 映射 state 的工具函数
export const mapState = (states) => {const store = useStore()const res = {}for (const key in states) {const value = states[key]res[key] = computed(() => {return typeof value === 'function' ? value(store.state, store.getters) : store.state[value]})}return res
}// 映射 getters 的工具函数
export const mapGetters = (getters) => {const store = useStore()const res = {}for (const key in getters) {res[key] = computed(() => store.getters[getters[key]])}return res
}
在组件中使用:
<script setup>
import { mapState, mapGetters } from './store/mappers'// 映射 state
const { count, user } = mapState({count: 'count', // 直接映射 state 中的 countuser: (state) => state.user.info // 支持函数形式
})// 映射 getters
const { doubleCount, userRole } = mapGetters({doubleCount: 'doubleCount',userRole: 'getUserRole'
})
</script>
3. 在 Options API 中使用(兼容方式)
如果在 Vue3 中仍使用 Options API,可直接沿用 Vue2 的映射方式:
<script>
import { mapState, mapGetters } from 'vuex'export default {computed: {// 映射 state...mapState(['count', 'user']),// 或带命名空间的映射...mapState('moduleName', ['count']),// 映射 getters...mapGetters(['doubleCount', 'userRole']),// 或带命名空间的映射...mapGetters('moduleName', ['doubleCount'])}
}
</script>
关键点说明:
- 响应式保证:
无论哪种方式,都必须通过computed
包裹,才能确保state
和getters
的响应性(Vuex 状态变化时组件会重新渲染)。 - 命名空间模块:
若使用带命名空间的模块,需在映射时指定模块名:
// 手动映射命名空间模块
const moduleCount = computed(() => store.state.moduleName.count)
const moduleGetter = computed(() => store.getters['moduleName/moduleGetter'])
- TypeScript 支持:
结合 TypeScript 时,建议手动映射并指定类型,获得更好的类型提示:
import { useStore } from 'vuex'
import { computed } from 'vue'
import type { State } from './store' // 导入状态类型定义const store = useStore<State>()
const count = computed(() => store.state.count) // 自动推断类型为 number
总结
- Vue3 中推荐使用
useStore
+computed
手动映射,更符合 Composition API 风格 - 如需兼容 Options API,可直接使用 Vuex 内置的
mapState
和mapGetters
- 无论哪种方式,都要确保通过
computed
保持响应性
如果是新项目,建议考虑 Vue 官方推荐的 Pinia(Vuex 的继任者),它的 API 更简洁,且原生支持 Composition API。