编程 uni-app 也能实现全局 Toast?这套方案彻底搞定!

2025-08-17 18:33:39 +0800 CST views 457

uni-app 也能实现全局 Toast?这套方案彻底搞定!

在日常的 uni-app 开发中,你是否遇到过这样的场景:

  • 网络请求失败时需要给用户一个全局提示;
  • 路由守卫中想要提醒用户“请先登录”;
  • 或者在业务逻辑深处,需要快速弹出一个 Toast。

问题是:uni-app 没有开箱即用的全局 Toast 方案uni.showToast() 功能太简单,样式难自定义;组件化的 Toast 又只能在当前页面使用,无法跨组件调用。

本文将带你实现一套完整的全局 Toast 解决方案,并且还能扩展到全局 Loading、MessageBox —— 真正做到 随时随地调用


一、问题分析

传统方案的局限性主要在于:

  1. uni.showToast()

    • 优点:调用方便。
    • 缺点:样式固定,无法扩展。
  2. 组件化 Toast

    • 优点:可定制。
    • 缺点:只能在当前组件调用,没法跨页面使用。
  3. Wot UI 的 useToast

    • 优点:函数式调用简洁。
    • 缺点:必须在 setup 顶层调用,无法在请求拦截器、路由守卫中使用。

核心原因在于:uni-app 不支持像 Vue3 一样挂载全局组件实例,因此无法在任意位置访问组件。


二、解决方案架构

要想解决这个问题,我们可以分三步:

  1. wd-toast 组件:提供基础能力;
  2. Layout 插件:一次性插入全局组件;
  3. useGlobalToast + Pinia:用状态管理来驱动 Toast,在任何地方都能调用。

三、实现步骤

1. 使用 wd-toast 组件

Wot UI 的 Toast 组件提供了函数式调用。

<script setup>
const toast = useToast('myToast')

// 显示提示
toast.show({
  msg: '这是一个提示',
  duration: 2000
})
</script>

<template>
  <wd-toast selector="myToast" />
</template>

但这样仍有局限:必须写在 setup 顶层,无法全局调用。


2. Layout 插件:一次插入,全局可用

layouts/default.vue 中统一插入全局组件:

<template>
  <wd-config-provider>
    <slot />
    <wd-toast />
    <global-toast />
    <global-loading />
    <global-message />
  </wd-config-provider>
</template>

这样所有页面都会自带这些全局组件,实现了“全局挂载”。


3. useGlobalToast + Pinia:全局状态驱动

我们用 Pinia 管理 Toast 的状态:

// useGlobalToast.ts
import { defineStore } from 'pinia'

export const useGlobalToast = defineStore('global-toast', {
  state: () => ({
    toastOptions: { show: false, duration: 2000 },
    currentPage: '',
  }),
  actions: {
    show(option) {
      this.currentPage = getCurrentPath()
      this.toastOptions = {
        ...this.toastOptions,
        ...(typeof option === 'string' ? { msg: option } : option),
        show: true,
      }
    },
    success(msg) {
      this.show({ msg, iconName: 'success', duration: 1500 })
    },
    error(msg) {
      this.show({ msg, iconName: 'error', direction: 'vertical' })
    },
    warning(msg) {
      this.show({ msg, iconName: 'warning' })
    },
    close() {
      this.toastOptions = { show: false, duration: 2000 }
    },
  },
})

全局组件 GlobalToast.vue 监听 toastOptions 的变化来显示/关闭 Toast。

<script setup>
const { toastOptions, currentPage } = storeToRefs(useGlobalToast())
const toast = useToast('globalToast')

watch(toastOptions, (opt) => {
  if (opt.show && currentPage.value === getCurrentPath())
    toast.show(opt)
  else
    toast.close()
})
</script>

<template>
  <wd-toast selector="globalToast" />
</template>

四、使用示例

在组件中使用

const globalToast = useGlobalToast()

globalToast.success('操作成功!')
globalToast.error('操作失败!')

在请求拦截器中使用

uni.addInterceptor('request', {
  fail() {
    useGlobalToast().error('网络请求失败')
  }
})

在路由守卫中使用

if (!isLogin()) {
  useGlobalToast().warning('请先登录')
  uni.navigateTo({ url: '/pages/login/index' })
  return false
}

五、扩展功能

基于相同思路,还能实现:

  • GlobalLoading:显示全局加载提示;
  • GlobalMessage:全局弹窗(alert、confirm);
  • Notify/MessageBox:快速拓展到更多交互场景。

六、总结

通过这套架构,我们实现了:

  1. 真正的全局调用:拦截器、守卫、任意逻辑中都能使用;
  2. 多端兼容:兼容小程序、H5、APP;
  3. 页面隔离:只在当前页面显示,不会出现跨页面混乱;
  4. 可扩展性强:同样的架构轻松扩展到 Loading、MessageBox。

如果你也在为 uni-app 全局 Toast 而烦恼,不妨试试这套方案。它不仅优雅,而且高度可扩展,让全局提示不再是难题! 🚀

推荐文章

mysql关于在使用中的解决方法
2024-11-18 10:18:16 +0800 CST
JavaScript设计模式:单例模式
2024-11-18 10:57:41 +0800 CST
全栈利器 H3 框架来了!
2025-07-07 17:48:01 +0800 CST
使用Rust进行跨平台GUI开发
2024-11-18 20:51:20 +0800 CST
Linux 网站访问日志分析脚本
2024-11-18 19:58:45 +0800 CST
Python设计模式之工厂模式详解
2024-11-19 09:36:23 +0800 CST
404错误页面的HTML代码
2024-11-19 06:55:51 +0800 CST
Rust开发笔记 | Rust的交互式Shell
2024-11-18 19:55:44 +0800 CST
H5保险购买与投诉意见
2024-11-19 03:48:35 +0800 CST
gin整合go-assets进行打包模版文件
2024-11-18 09:48:51 +0800 CST
全栈工程师的技术栈
2024-11-19 10:13:20 +0800 CST
Vue中的`key`属性有什么作用?
2024-11-17 11:49:45 +0800 CST
智慧加水系统
2024-11-19 06:33:36 +0800 CST
PHP 如何输出带微秒的时间
2024-11-18 01:58:41 +0800 CST
程序员茄子在线接单