Vue3选项API下如何在Pinia Store中调用$toast?
问题:Pinia Store中调用@meforma/vue-toaster报错
Can not read properties of undefined (reading 'success') 我正在使用Vue3选项API、Pinia以及@meforma/vue-toaster,已按文档要求在main.js中导入toaster,组件中使用完全正常。现需在Pinia Store的store.js中按如下代码调用$toast:
actions: { async login(data) { try { const res = await authService.login(data); if (res.data.msg == "success") { this.$toast.success("loged in successfully", { position: "bottom-right", duration: 3000, type: 'success', }); } } catch (error) { this.$toast.error(error.res.data.error, { position: "bottom-right", duration: 5000, type: 'error', }); } } }, }
但运行后报错:Can not read properties of undefined (reading 'success'),请问问题出在哪里?
问题原因
Pinia的Store实例和Vue组件实例是相互独立的。你在main.js里把toaster挂载到Vue全局属性$toast后,只有Vue组件实例能继承这个属性,而Store里的this指向的是Store自身,并没有$toast这个属性,所以会报undefined的错误。
另外你代码里还有个小问题:catch块里的error.res应该是error.response(Axios错误对象的响应属性是response),不然也会拿不到错误信息。
解决办法
方法1:直接导入全局toaster实例
在main.js里把全局的toaster实例导出,然后在Store里导入使用:
- 修改main.js:
import { createApp } from 'vue' import App from './App.vue' import Toaster from '@meforma/vue-toaster' import { createPinia } from 'pinia' const app = createApp(App) const pinia = createPinia() // 挂载toaster app.use(Toaster) app.use(pinia) // 导出全局的toaster实例 export const toast = app.config.globalProperties.$toast app.mount('#app')
- 在store.js里导入并使用:
import { defineStore } from 'pinia' import { toast } from '../main' import authService from './your-auth-service-path' export const useAuthStore = defineStore('auth', { actions: { async login(data) { try { const res = await authService.login(data); if (res.data.msg == "success") { toast.success("logged in successfully", { position: "bottom-right", duration: 3000, type: 'success', }); } } catch (error) { toast.error(error.response?.data?.error || '登录失败', { position: "bottom-right", duration: 5000, type: 'error', }); } } } })
方法2:通过Pinia插件全局注入toaster
如果项目里多个Store都需要用到toaster,可以封装成Pinia插件来全局注入:
- 创建pinia插件文件
plugins/toaster.js:
import { toast } from '../main' export function toasterPlugin({ store }) { store.$toast = toast }
- 在main.js里注册插件:
import { createPinia } from 'pinia' import { toasterPlugin } from './plugins/toaster' const pinia = createPinia() pinia.use(toasterPlugin) app.use(pinia)
- 之后就能在Store的action里直接用
this.$toast了,和你原来的代码写法一致,不用修改调用逻辑。
内容的提问来源于stack exchange,提问作者morteza mortezaie
相关产品推荐
相关产品推荐

