Pinia Store调用带i18n的toast函数报setup相关错误如何解决?
报错原因
useI18n 和 vue-toastification 提供的 useToast 都属于Vue组合式API专属钩子,只能在组件setup函数顶层或者在setup顶层调用的组合式函数同步上下文中运行。你在Pinia的action内调用useToastMsg时,执行上下文已经脱离了setup环境,因此触发报错。
可行解决方案
方案1:抽离全局实例,改写composable(最通用,无需依赖调用上下文)
不需要依赖setup环境,改完后组件、Pinia、普通工具函数里都能直接调用。
- 单独抽离i18n实例,新建
src/i18n/index.js:
import { createI18n } from 'vue-i18n' // 引入你自己的语言包 import zhCN from './locales/zh-CN.json' import enUS from './locales/en-US.json' const i18n = createI18n({ legacy: false, // 组合式API模式必须设为false locale: 'zh-CN', messages: { 'zh-CN': zhCN, 'en-US': enUS } }) // 导出全局翻译函数,不用再调用useI18n拿t export const t = i18n.global.t export default i18n
- 在
main.js正常注册i18n,同时导出toast全局实例:
import { createApp } from 'vue' import App from './App.vue' import i18n from './i18n' import Toast from "vue-toastification" import "vue-toastification/dist/index.css" const app = createApp(App) // 注册toast,按你自己的需求填配置 app.use(Toast, { position: "top-right", timeout: 3000 }) // 导出全局toast实例 export const toast = app.config.globalProperties.$toast app.use(i18n) app.mount('#app')
- 改写你的toast composable,直接用全局实例,不用调用use钩子:
import { toast } from '@/main' import { t } from '@/i18n' export default function useToastMsg(message, type) { if (type === "success") { return toast.success(t(message)) } else if (type === "error") { return toast.error(t(message)) } }
改完后直接在Pinia的action里按原来的写法调用即可,不会再报错。
方案2:调用时传入上下文实例
不想修改现有封装逻辑的话可以用这个方案,在组件调用action时把当前setup上下文的t和toast实例传进去。
- 改写composable接收实例参数:
export default function useToastMsg(t, toast, message, type) { if (type === "success") { return toast.success(t(message)) } else if (type === "error") { return toast.error(t(message)) } }
- 组件内调用action时传参:
<script setup> import { useI18n } from 'vue-i18n' import { useToast } from "vue-toastification" import { useYourStore } from '@/stores/yourStore' const { t } = useI18n() const toast = useToast() const store = useYourStore() const handleSubmit = async () => { // 调用action时传入t和toast实例 await store.submitAction(t, toast) } </script>
- Pinia的action接收参数后调用:
import useToast from "@/composables/toast" // 选项式写法的store actions: { async submitAction(t, toast) { // 你的业务逻辑 useToast(t, toast, "submit", "success") } }
方案3:Pinia用组合式写法,顶层调用use钩子
如果你用组合式写法定义Pinia store,可以直接在store顶层调用use钩子,符合调用规则:
import { defineStore } from 'pinia' import { useI18n } from 'vue-i18n' import { useToast } from "vue-toastification" export const useYourStore = defineStore('yourStore', () => { // store顶层调用use钩子,和组件setup规则一致 const { t } = useI18n() const toast = useToast() const submitAction = async () => { // 业务逻辑执行完成直接调用 toast.success(t("submit")) } return { submitAction } })
内容的提问来源于stack exchange,提问作者Dave
相关产品推荐
相关产品推荐

