尧图网站建设 尧图网络
  • 首页
  • 关于我们
  • 服务项目
  • 案例展示
  • 建站流程
  • 资讯中心
  • 联系我们
首页/资讯中心/详情

uni-app 无法实现全局 Toast?这个方法做到了!

uni-app 无法实现全局 Toast?这个方法做到了!
📅 发布时间:2026/6/20 16:14:01

🧑‍💻 写在开头

点赞 + 收藏 === 学会🤣🤣🤣

大家好,我是不如摸鱼去,wot-ui的主要维护者,欢迎来到我的 uni-app 分享专栏。

在 uni-app 开发中,我们经常遇到需要在任何地方(如网络请求拦截器、>路由守卫等)显示 Toast 提示的需求。然而,uni-app 的组件化架构使>得全局 Toast 的实现变得复杂。本文将介绍一套完整的解决方案,让你轻松>实现真正的全局 Toast。

本文实现的全局 Toast、Loading、MessageBox 等组件均已在现代化 uni-app 模板,基于vitesse-uni-app的深度整合 Wot UI 组件库的快速起手项目 wot-demo 中提供,模板地址在文章末尾,作者是其主要维护者。

问题分析

传统方案的局限性

在 uni-app 中,常见的 Toast 实现方式有以下几种:

  1. uni.showToast() - 功能有限,样式单一,无法自定义
  2. 传统Toast - 只能在当前组件使用,无法跨组件调用
  3. wot ui 方案 - 基于provide/inject实现,需要在 setup 顶层调用useToast,无法在路由拦截和请求拦截中使用

核心难点

  • uni-app 无法像 Vue 3 那样全局挂载组件
  • 组件实例无法在非 Vue 上下文中访问
  • 需要在网络请求和路由拦截中使用 Toast

解决方案架构

我们的解决方案包含三个核心部分:

  1. wd-toast 组件 - 基于 provide/inject 的函数式调用
  2. Layout 插件 - 实现一次插入,全局可用
  3. useGlobalToast - 基于 Pinia 的状态管理

实现详解

1. wd-toast 组件实现

wot ui 是一个当下流行的 uni-app vue3 UI 库,作者也是其重要维护者之一。

首先,我们使用 wot-ui 的 Toast 组件,它基于 provide/inject 实现函数式调用:

<!-- 在组件中使用 -->
<script setup>
const toast = useToast('myToast')// 显示 Toast
toast.show({msg: '这是一个提示',duration: 2000
})
</script><template><wd-toast selector="myToast" />
</template>

优点: 函数式调用,使用简单 缺点: useToast 必须在 setup 顶层调用,toast.show 仅能在vue组件中使用

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

由于 uni-app 无法全局插入组件,我们通过 @uni-helper/vite-plugin-uni-layouts 插件实现统一布局管理:

<!-- src/layouts/default.vue -->
<template><wd-config-provider :theme-vars="themeVars" :theme="theme"><slot /><!-- 全局组件一次性插入 --><wd-notify /><wd-message-box /><wd-toast /><global-loading /><global-toast /><global-message /></wd-config-provider>
</template>

这样,所有页面都会包含这些全局组件,实现了"一次插入,全局可用"的效果。

3. GlobalToast 组件实现

<!-- src/components/GlobalToast.vue -->
<script lang="ts" setup>
const { toastOptions, currentPage } = storeToRefs(useGlobalToast())
const { close: closeGlobalToast } = useGlobalToast()const toast = useToast('globalToast')
const currentPath = getCurrentPath()// 支付宝小程序兼容性处理
// #ifdef MP-ALIPAY
const hackAlipayVisible = ref(false)
nextTick(() => {hackAlipayVisible.value = true
})
// #endif// 监听全局状态变化
watch(() => toastOptions.value, (newVal) => {if (newVal && newVal.show) {// 只在当前页面显示 Toastif (currentPage.value === currentPath) {toast.show(toastOptions.value)}}else {toast.close()}
})
</script><template><!-- 支付宝小程序特殊处理 --><!-- #ifdef MP-ALIPAY --><wd-toast v-if="hackAlipayVisible" selector="globalToast" :closed="closeGlobalToast" /><!-- #endif --><!-- #ifndef MP-ALIPAY --><wd-toast selector="globalToast" :closed="closeGlobalToast" /><!-- #endif -->
</template>

关键特性:

  • 通过 currentPage 确保 Toast 只在正确的页面显示
  • 支持支付宝小程序的兼容性处理
  • 使用 virtualHost 和 styleIsolation 优化结构和样式

4. useGlobalToast - Pinia 状态管理

// src/composables/useGlobalToast.ts
import { defineStore } from 'pinia'
import type { ToastOptions } from 'wot-design-uni/components/wd-toast/types'interface GlobalToast {toastOptions: ToastOptionscurrentPage: string
}const defaultOptions: ToastOptions = {duration: 2000,show: false,
}export const useGlobalToast = defineStore('global-toast', {state: (): GlobalToast => ({toastOptions: defaultOptions,currentPage: '',}),actions: {// 显示 Toastshow(option: ToastOptions | string) {this.currentPage = getCurrentPath()const options = CommonUtil.deepMerge(defaultOptions,typeof option === 'string' ? { msg: option } : option) as ToastOptionsthis.toastOptions = CommonUtil.deepMerge(options, {show: true,position: options.position || 'middle',}) as ToastOptions},// 成功提示success(option: ToastOptions | string) {this.show(CommonUtil.deepMerge({iconName: 'success',duration: 1500,}, typeof option === 'string' ? { msg: option } : option) as ToastOptions)},// 错误提示error(option: ToastOptions | string) {this.show(CommonUtil.deepMerge({iconName: 'error',direction: 'vertical',}, typeof option === 'string' ? { msg: option } : option) as ToastOptions)},// 信息提示info(option: ToastOptions | string) {this.show(CommonUtil.deepMerge({iconName: 'info',}, typeof option === 'string' ? { msg: option } : option) as ToastOptions)},// 警告提示warning(option: ToastOptions | string) {this.show(CommonUtil.deepMerge({iconName: 'warning',}, typeof option === 'string' ? { msg: option } : option) as ToastOptions)},// 关闭 Toastclose() {this.toastOptions = defaultOptionsthis.currentPage = ''},},
})

使用方式

1. 在组件中使用

<script setup>
const globalToast = useGlobalToast()function handleClick() {globalToast.success('操作成功!')globalToast.error('操作失败!')globalToast.info('提示信息')globalToast.warning('警告信息')
}
</script>

2. 在网络请求中使用

// 请求拦截器
uni.addInterceptor('request', {fail(err) {const globalToast = useGlobalToast()globalToast.error('网络请求失败')}
})// 或在 API 封装中
export async function apiRequest(url: string, data: any) {try {const result = await uni.request({ url, data })return result}catch (error) {const globalToast = useGlobalToast()globalToast.error('请求失败,请重试')throw error}
}

3. 在路由拦截中使用

// 路由守卫
function routeGuard(to: string) {const globalToast = useGlobalToast()if (!isLogin()) {globalToast.warning('请先登录')uni.navigateTo({ url: '/pages/login/index' })return false}return true
}

扩展功能

基于同样的架构,我们还实现了:

1. GlobalLoading - 全局加载提示

export const useGlobalLoading = defineStore('global-loading', {actions: {loading(option: ToastOptions | string) {this.currentPage = getCurrentPath()this.loadingOptions = CommonUtil.deepMerge({iconName: 'loading',duration: 0,cover: true,position: 'middle',show: true,}, typeof option === 'string' ? { msg: option } : option)}}
})

2. GlobalMessage - 全局弹窗

export const useGlobalMessage = defineStore('global-message', {actions: {alert(option: GlobalMessageOptions | string) {const messageOptions = CommonUtil.deepMerge({ type: 'alert' },CommonUtil.isString(option) ? { title: option } : option)messageOptions.showCancelButton = falsethis.show(messageOptions)}}
})

总结

通过这套方案,我们成功解决了 uni-app 全局 Toast 的难题:

  1. wd-toast 组件 提供了优秀的基础能力
  2. @uni-helper/vite-plugin-uni-layouts 插件 实现了统一布局和组件的全局插入
  3. Pinia 状态管理 让我们能在任何地方调用 Toast

这个方案具有以下优势:

  • 真正的全局调用,可在任何地方使用
  • 完整的类型支持
  • 多端兼容性
  • 页面隔离机制

如果你也在为 uni-app 的全局 Toast 而烦恼,不妨试试这个方案!

如果对您有所帮助,欢迎您点个关注,我会定时更新技术文档,大家一起讨论学习,一起进步。

相关新闻

  • 2025较好的留学机构排名前十
  • 使用 x11vnc 与 systemd 实现持久化 VNC 远程桌面服务
  • 2025 最新珩磨管厂家推荐!珩磨管 / 活塞杆 / 合金管 / 精密无缝管优质品牌排行榜,含 20#45#/304 材质数控珩磨工艺企业权威推荐

最新新闻

  • ​2026 年临沂红胡桃木全屋定制工厂深度解析:六家口碑厂家详评与优选指南 - 新闻快传
  • 2026广州白蚁消杀所VS青林、匿名实测,设备与技术代际差距 - 博客万
  • 哈尔滨旅游必打卡清真美食店排行 实测口碑Top5 - 起跑123
  • GLM-5.2 强到能冒充 Claude:架构师视角拆解国产开源模型战力
  • 2026南京奢品私密交易白皮书,一对一交割,严防隐私泄露 - 讯息早知道
  • 嵌入式GUI图像优化:从位图转换到性能调优的完整指南

日新闻

  • 信任的进化:技术实现详解——如何用JavaScript构建博弈论模拟器
  • Terrakube自定义工作流:如何集成OPA、Infracost等工具扩展IaC能力
  • grunt-concurrent快速入门:5分钟学会并行运行Grunt任务

周新闻

  • 3步解锁iOS设备:applera1n激活锁绕过完全指南
  • 39 2026 人工智能证书终极盘点,普通人选 AI 证书可以从这些方向入手
  • Redis 暴露公网有多危险?从端口检查到补救步骤

月新闻

  • 【总结】入门篇:50句话让你记住架构核心概念
  • WeChatMsg技术方案解析:实现Mac微信数据自主管理的完整解决方案
  • WeChatMsg:革新性微信数据备份方案,打造你的专属数字记忆库

关于尧图

  • 公司简介
  • 团队介绍
  • 企业文化
  • 荣誉资质

服务项目

  • 定制开发
  • 电商建站
  • UI 设计
  • 运维服务

快速链接

  • 案例展示
  • 建站流程
  • 常见问题
  • 资讯中心

联系方式

  • 📍北京市朝阳区互联网产业园 A 座 10 层
  • 📞400-888-8888
  • ✉️contact@rkmt.cn
  • 🕐周一至周日 9:00-21:00

© 2024 北京尧图网络科技有限公司 版权所有 | 京 ICP 备 XXXXXXXX 号