如何将Vuex mapGetters与Vue 3 SFC脚本设置语法一起使用



我正在将组件从常规Vue 3 Composition API重构为Script Setup语法。起点:

<script lang="ts">
import { defineComponent, computed } from 'vue';
import { mapGetters } from 'vuex';
export default defineComponent({
name: 'MyCoolBareComponent',
computed: {
...mapGetters('auth', ['isAdmin']),
},
});
</script>

当前Vue v3迁移文档,SFC Composition API Syntax Sugar(<script setup>(,链接到此RFC页面:https://github.com/vuejs/rfcs/pull/182

只有一个使用计算反应性的例子:

export const computedMsg = computed(() => props.msg + '!!!')

由于目前没有提到<scrip setup>的Vuex 4文档,我不清楚在使用此语法时应该如何使用mapGetters?或者Vuex 4的正确方式是什么

tldr:向下滚动到最终结果

现在有了更好的文档,简单的答案是:您不需要mapGetters,但您可以自己实现它。

https://next.vuex.vuejs.org/guide/composition-api.html#accessing-状态和getters

<script setup>
import { computed } from 'vue'
import { useStore } from 'vuex'
const store = useStore()
const count = computed(() => store.getters.count)
</script>

如果你有很多胡瓜,你想把它们变成"胡瓜";计算性质";你可以用";直观的";如下:

const { countIsOdd, countIsEven } = Object.fromEntries(Object.keys(store.getters).map(getter => [getter, computed(() => store.getters[getter])]))

把它放进一个函数中,它甚至看起来很好看。

const mapGetters = (getters) => {
return Object.fromEntries(Object.keys(getters).map(getter => [getter, computed(() => getters[getter])]))
}
const { countIsOdd, countIsEven } = mapGetters(store.getters)

将该函数放入文件中,并将其导出为模块。。。

// lib.js
import { computed } from 'vue'
import { useStore } from 'vuex'
const mapGetters = () => {
const store = useStore()
return Object.fromEntries(Object.keys(store.getters).map(getter => [getter, computed(() => store.getters[getter])]))
}
export { mapGetters }

并且您可以在所有组件中轻松使用它。

// components/MyComponent.vue
<script setup>
import { mapGetters } from '../lib'
const { countIsOdd, countIsEven } = mapGetters()
</script>

最终结果:

这是我最后想到的lib.js:

import { computed } from 'vue'
import { useStore } from 'vuex'
const mapState = () => {
const store = useStore()
return Object.fromEntries(
Object.keys(store.state).map(
key => [key, computed(() => store.state[key])]
)
)
}
const mapGetters = () => {
const store = useStore()
return Object.fromEntries(
Object.keys(store.getters).map(
getter => [getter, computed(() => store.getters[getter])]
)
)
}
const mapMutations = () => {
const store = useStore()
return Object.fromEntries(
Object.keys(store._mutations).map(
mutation => [mutation, value => store.commit(mutation, value)]
)
)
}
const mapActions = () => {
const store = useStore()
return Object.fromEntries(
Object.keys(store._actions).map(
action => [action, value => store.dispatch(action, value)]
)
)
}
export { mapState, mapGetters, mapMutations, mapActions }

在组件中使用这个看起来像这样:

<template>
Count: {{ count }}
Odd: {{ counterIsOdd }}
Even: {{ counterIsEven }}
<button @click="countUp">count up</button>
<button @click="countDown">count down</button>
<button @click="getRemoteCount('https://api.countapi.xyz')">
get remote count
</button>
</template>
<script setup>
import { mapState, mapGetters, mapMutations, mapActions } from '../lib'
// computed properties
const { count } = mapState()
const { countIsOdd, countIsEvent } = mapGetters()
// commit/dispatch functions
const { countUp, countDown } = mapMutations()
const { getRemoteCount } = mapActions()
</script>

如有任何反馈,我们将不胜感激。

到目前为止,这种语法似乎是有效的。然而,我希望Vuex能够开发出一种更干净的方式来公开模板的计算getter。

如果你知道更好的方法,我们很乐意听到

<script setup lang="ts">
import { mapGetters } from 'vuex';
export const name = 'MyCoolBareComponent';
export default {
computed: {
...mapGetters('user', ['profile', 'roles']),
},
};
</script>
import {useStore} from "vuex";
import {computed} from "vue";

const {getEvents, getSelectedTag} = useStore().getters;
const events = computed(() => getEvents)
const selectedTag = computed(() => getSelectedTag)

我这样做,对我来说是

您不需要导出任何内容,SFC将为您注册所有变量和组件,并使它们在template中可用。

SFC会自动从其文件名推断出组件的名称。

以下是一些可能有用的例子:

<script setup>
import { computed } from 'vue'
import { useStore } from 'vuex'
import MyComponent from './components/MyComponent'
const store = useStore()
const data = 'Random string as a data'
// without module/data 
const myAction = () => store.dispatch('myAction')
// with data
const mySecondAction = () => store.dispatch('mySecondAction', data)
// with module
const myMutation = () => store.commit('moduleName/myMutation')
// with module/data
const myNewMutation = () => store.commit('moduleName/myNewMutation', data)
const myStateVariable = computed(() => store.state.myStateVariable)
// with module
const myGetter = computed(() => store.getters.moduleName.myGetter)
// replace using of mapState/mapGetters
const state = computed(() => store.state)
// and then
console.log(state.myStateVariable)
console.log(state.mySecondStateVariable)
....
</script>

遵循以下步骤:
https://vuex.vuejs.org/guide/typescript-support.html#typing-usestore合成函数

这里有一个例子:

  • 商店.ts
import { InjectionKey } from 'vue'
import { createStore, Store } from 'vuex'
// define your typings for the store state
export interface State {
token: string|null
}
// define injection key
export const key: InjectionKey<Store<State>> = Symbol()
export const store = createStore<State>({
state: {
token: localStorage.getItem('token') ? localStorage.getItem('token'):'',
}
})
  • main.js
import { store, key } from './store'
import { createApp } from 'vue'
import App from './App.vue'
const app = createApp(App)
// pass the injection key
app
.use(store, key)
.mount('#app')
  • 在vue组件中
<script setup>
import { onMounted } from 'vue'
import { useStore } from 'vuex'
import { key } from './store'
const token = useStore(key) 
onMounted(() => {
console.log(store.state.token)
})
</script>

您可以执行类似的操作

import { mapGetters } from "vuex"
setup() {
return {
...mapGetters("myModule", ["doSomething"])
}
}

最新更新