You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Pinia Store中调用$toast?附示例(Vue3选项式API)

在Pinia Store中处理提示与Axios的最佳实践

一、直接在Store中调用toaster/swal的实现方式

如果只是快速实现需求,直接在Store中导入库或通过全局属性访问是可行的:

1. 直接导入toaster库(以vue-toastification为例)

// stores/yourStore.js
import { defineStore } from 'pinia'
import axios from 'axios'
import { useToast } from 'vue-toastification'

const toast = useToast()

export const useYourStore = defineStore('yourStore', {
  actions: {
    async fetchData() {
      try {
        const response = await axios.get('/api/data')
        toast.success('数据获取成功!')
        return response.data
      } catch (error) {
        toast.error(`请求失败:${error.message}`)
        throw error // 抛出错误让组件可处理后续逻辑
      }
    }
  }
})

2. 通过app全局属性访问(适合$swal这类挂载到全局的工具)

若已将swal挂载到app全局属性(如app.config.globalProperties.$swal = Swal),可通过Pinia的this.$app访问:

// stores/yourStore.js
import { defineStore } from 'pinia'
import axios from 'axios'

export const useYourStore = defineStore('yourStore', {
  actions: {
    async submitForm(data) {
      try {
        await axios.post('/api/submit', data)
        this.$app.config.globalProperties.$swal('成功!', '表单提交完成', 'success')
      } catch (error) {
        this.$app.config.globalProperties.$swal('失败!', error.message, 'error')
        throw error
      }
    }
  }
})

二、最佳实践:让Store聚焦业务,UI逻辑交给组件

Store的核心职责是管理状态、处理业务逻辑,耦合UI提示会导致Store难以复用、测试,违背关注点分离原则。最佳方案是:

  • Store只负责发起请求、处理业务,成功/失败时返回结果或抛出错误
  • 组件调用Store的action,在组件内处理UI提示

示例实现

1. Store文件(纯业务逻辑)

// stores/yourStore.js
import { defineStore } from 'pinia'
import axios from 'axios'

export const useYourStore = defineStore('yourStore', {
  state: () => ({
    data: null
  }),
  actions: {
    async fetchData() {
      try {
        const response = await axios.get('/api/data')
        this.data = response.data
        return { success: true, message: '数据获取成功' }
      } catch (error) {
        return { success: false, message: `请求失败:${error.message}` }
      }
    },

    async submitForm(data) {
      try {
        await axios.post('/api/submit', data)
        return { success: true, message: '表单提交成功' }
      } catch (error) {
        throw new Error(`提交失败:${error.message}`)
      }
    }
  }
})

2. 组件文件(处理UI提示)

<template>
  <button @click="handleFetch">获取数据</button>
  <button @click="handleSubmit">提交表单</button>
</template>

<script>
import { useYourStore } from '@/stores/yourStore'
import { useToast } from 'vue-toastification'
import Swal from 'sweetalert2'

export default {
  setup() {
    const store = useYourStore()
    const toast = useToast()

    const handleFetch = async () => {
      const result = await store.fetchData()
      result.success ? toast.success(result.message) : toast.error(result.message)
    }

    const handleSubmit = async () => {
      try {
        const result = await store.submitForm({ name: 'test' })
        Swal.fire('成功', result.message, 'success')
      } catch (error) {
        Swal.fire('失败', error.message, 'error')
      }
    }

    return { handleFetch, handleSubmit }
  }
}
</script>

三、进阶方案:封装Axios拦截器统一处理提示

如果多个请求都需要提示,可封装Axios拦截器统一处理,避免重复代码:

// utils/axios.js
import axios from 'axios'
import { useToast } from 'vue-toastification'
import Swal from 'sweetalert2'

const toast = useToast()
const instance = axios.create({ baseURL: '/api' })

// 响应拦截器
instance.interceptors.response.use(
  (response) => {
    // 可根据后端返回的code判断是否提示
    if (response.data.code === 200 && response.data.message) {
      toast.success(response.data.message)
    }
    return response
  },
  (error) => {
    const message = error.response?.data?.message || '请求出错'
    Swal.fire('错误', message, 'error')
    return Promise.reject(error)
  }
)

export default instance

之后在Store和组件中使用这个封装后的Axios实例,既统一了提示逻辑,又保持Store的纯净性。

内容的提问来源于stack exchange,提问作者KHALED OGHLI

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.23 14:36:19