Skip to content

useToast 轻提示

介绍

useToast 是一个专为 UniApp 应用设计的轻量级消息提示 Composable,提供了优雅、灵活的全局消息提示功能。

核心特性:

  • 全局队列管理 - 基于 Map 数据结构管理所有活跃的 Toast 实例,支持多实例并发显示
  • 自动堆叠布局 - 智能计算每个 Toast 的垂直偏移量,避免重叠覆盖
  • 层级自动管理 - 基于 BASE_Z_INDEX(1000) 自动分配 zIndex
  • 单例模式缓存 - 每个 selector 对应唯一的 Toast 实例
  • 五种预设方法 - 提供 loading、success、error、warning、info 五种常用消息类型
  • 自动关闭定时器 - 支持配置显示时长,可设置 duration=0 实现手动关闭
  • TypeScript 支持 - 完整的类型定义
  • 平台兼容性 - 支持 H5、微信小程序、App 等多个 UniApp 平台

基本用法

简单文本提示

vue
<template>
  <view class="demo">
    <wd-button @click="showToast">显示提示</wd-button>
  </view>
</template>

<script lang="ts" setup>
import { useToast } from '@/wd'

const toast = useToast()

const showToast = () => {
  toast.show('这是一条简单的提示消息')
}
</script>

预设类型提示

vue
<script lang="ts" setup>
import { useToast } from '@/wd'

const toast = useToast()

// 成功提示 - 绿色图标,1500ms
toast.success('提交成功')

// 错误提示 - 红色图标,2000ms
toast.error('删除失败,请稍后重试')

// 警告提示 - 橙色图标,2000ms
toast.warning('库存不足,请及时补货')

// 信息提示 - 蓝色图标,2000ms
toast.info('长按列表项可进行更多操作')
</script>

加载提示

加载提示默认不自动关闭,需要手动调用 close():

vue
<script lang="ts" setup>
import { useToast } from '@/wd'

const toast = useToast()

const handleLoad = async () => {
  toast.loading('加载中...')

  try {
    await fetchData()
    toast.close()
    toast.success('加载完成')
  } catch (error) {
    toast.close()
    toast.error('加载失败')
  }
}
</script>

自定义配置

vue
<script lang="ts" setup>
import { useToast } from '@/wd'
import type { ToastOptions } from '@/wd'

const toast = useToast()

const showCustomToast = () => {
  const options: ToastOptions = {
    msg: '自定义样式的提示消息',
    duration: 3000,
    position: 'bottom',
    iconName: 'success',
    iconSize: 48,
    iconColor: '#00c853',
    direction: 'horizontal',
  }

  toast.show(options)
}
</script>

不同位置的 Toast

vue
<script lang="ts" setup>
import { useToast } from '@/wd'

const toast = useToast()

// 顶部
toast.show({ msg: '顶部提示', position: 'top' })

// 中上部(默认)
toast.show({ msg: '中上提示', position: 'middle-top' })

// 中部
toast.show({ msg: '中部提示', position: 'middle' })

// 底部
toast.show({ msg: '底部提示', position: 'bottom' })
</script>

高级用法

多实例管理

使用 selector 参数创建多个独立的 Toast 实例:

vue
<script lang="ts" setup>
import { useToast } from '@/wd'

// 创建不同的实例
const mainToast = useToast('main')
const secondaryToast = useToast('secondary')

mainToast.success('主要操作成功')
secondaryToast.info('次要信息')
</script>

加载状态切换

vue
<script lang="ts" setup>
import { useToast } from '@/wd'

const toast = useToast()

const handleUpload = async () => {
  toast.loading({
    msg: '正在上传...',
    loadingType: 'ring',
    loadingColor: '#1890ff',
  })

  try {
    await uploadFile()
    toast.close()
    toast.success({ msg: '上传成功', duration: 2000 })
  } catch (error) {
    toast.close()
    toast.error({ msg: '上传失败,请重试', duration: 3000 })
  }
}
</script>

回调函数

vue
<script lang="ts" setup>
import { useToast } from '@/wd'

const toast = useToast()

toast.show({
  msg: '带回调的提示消息',
  duration: 2000,
  opened: () => {
    console.log('Toast 已完全展示')
  },
  closed: () => {
    console.log('Toast 已完全关闭')
  },
})
</script>

遮罩层控制

vue
<script lang="ts" setup>
import { useToast } from '@/wd'

const toast = useToast()

// 带遮罩的提示(阻止用户操作)
toast.show({
  msg: '这是一条重要提示',
  duration: 3000,
  cover: true,
  iconName: 'warning',
})
</script>

API

useToast()

创建或获取 Toast 实例。

typescript
function useToast(selector?: string): Toast

返回值方法:

方法说明类型
show显示 Toast(option: ToastOptions | string) => void
success显示成功 Toast(option: ToastOptions | string) => void
error显示错误 Toast(option: ToastOptions | string) => void
warning显示警告 Toast(option: ToastOptions | string) => void
info显示信息 Toast(option: ToastOptions | string) => void
loading显示加载 Toast(option: ToastOptions | string) => void
close关闭当前 Toast() => void

预设配置

方法iconNameduration其他
success'success'1500-
error'error'2000-
warning'warning'2000-
info'info'2000-
loading'loading'0cover: true

ToastOptions

属性说明类型默认值
msg提示信息string-
duration显示时长(ms),0表示不自动关闭number2000
direction图标和文字排列方向'vertical' | 'horizontal''vertical'
iconName图标名称'success' | 'error' | 'warning' | 'loading' | 'info' | ''''
iconSize图标大小(rpx)number42
iconColor图标颜色string-
loadingType加载图标类型'outline' | 'ring''outline'
loadingColor加载图标颜色string'#4D80F0'
positionToast 位置'top' | 'middle-top' | 'middle' | 'bottom''middle-top'
zIndex层级number1000
cover是否显示遮罩层booleanfalse
iconClass图标自定义类名string''
classPrefix图标类名前缀string'wd-icon'
opened完全展示后的回调() => void-
closed完全关闭后的回调() => void-

工具函数

函数说明
getToastOption(selector?)获取或创建指定 selector 的 Toast 配置
clearToastOption(selector?)清理指定 selector 的 Toast 配置缓存
clearAllToastOptions()清理所有 Toast 配置缓存
cleanupClosedToasts()清理已关闭的 Toast 实例

类型定义

typescript
// 图标类型
type ToastIconType = 'success' | 'error' | 'warning' | 'loading' | 'info' | ''

// 位置类型
type ToastPositionType = 'top' | 'middle-top' | 'middle' | 'bottom'

// 排列方向
type ToastDirection = 'vertical' | 'horizontal'

// 加载图标类型
type ToastLoadingType = 'outline' | 'ring'

// Toast 实例接口
interface Toast {
  show: (toastOptions: ToastOptions | string) => void
  success: (toastOptions: ToastOptions | string) => void
  error: (toastOptions: ToastOptions | string) => void
  info: (toastOptions: ToastOptions | string) => void
  warning: (toastOptions: ToastOptions | string) => void
  loading: (toastOptions: ToastOptions | string) => void
  close: () => void
}

// 常量
const TOAST_HEIGHT = 60     // Toast 基础高度(px)
const BASE_Z_INDEX = 1000   // 基础层级

最佳实践

1. 合理选择提示类型

typescript
// ✅ 根据操作结果选择类型
const handleSave = async () => {
  try {
    await saveData()
    toast.success('保存成功')
  } catch (error) {
    toast.error('保存失败')
  }
}

// ❌ 所有场景都用 show
toast.show('删除成功')  // 应该用 toast.success()

2. 正确管理 loading 状态

typescript
// ✅ 使用 try-finally 确保关闭
const handleSubmit = async () => {
  toast.loading('提交中...')
  try {
    await submitForm()
    toast.success('提交成功')
  } catch (error) {
    toast.error('提交失败')
  } finally {
    toast.close()
  }
}

3. 避免 Toast 滥用

typescript
// ✅ 批量操作后统一提示
const handleBatchDelete = async (items: any[]) => {
  toast.loading('批量删除中...')
  try {
    await Promise.all(items.map(item => deleteItem(item)))
    toast.close()
    toast.success(`成功删除 ${items.length} 条数据`)
  } catch (error) {
    toast.close()
    toast.error('批量删除失败')
  }
}

// ❌ 循环中频繁显示
items.forEach(item => {
  toast.success(`删除 ${item.name} 成功`)  // 可能堆叠几十个
})

4. 合理设置显示时长

typescript
// 短消息: 默认时长
toast.success('保存成功')

// 长消息: 延长时长
toast.info({
  msg: '您的订单已提交,预计1-2个工作日内发货',
  duration: 4000,
})

// 动态计算时长
const showDynamic = (msg: string) => {
  const duration = Math.min(2000 + Math.floor(msg.length / 10) * 500, 5000)
  toast.show({ msg, duration })
}

5. 使用多实例隔离

typescript
// ✅ 不同功能模块使用不同实例
const formToast = useToast('form')
const uploadToast = useToast('upload')

// 表单和上传可以独立控制,互不干扰
formToast.loading('提交中...')
uploadToast.loading('上传中...')

常见问题

1. Toast 不显示

原因: 未在页面中放置 <wd-toast /> 组件

解决:

vue
<template>
  <view class="page">
    <!-- 页面内容 -->
    <wd-toast />
    <!-- 如果使用命名实例 -->
    <wd-toast selector="main" />
  </view>
</template>

2. loading Toast 无法关闭

原因: 忘记调用 close() 或异常未捕获

解决: 使用 try-finally 确保关闭

typescript
toast.loading('加载中...')
try {
  await fetchData()
} finally {
  toast.close()
}

3. 多个 Toast 重叠显示

原因: 相同 selector 的 Toast 组件放置多次

解决: 每个 selector 只放置一次组件,让系统自动管理 zIndex

4. 小程序平台层级问题

原因: 小程序原生组件(map、video)层级高于普通元素

解决:

typescript
toast.success({
  msg: '操作成功',
  zIndex: 99999,  // 提高层级
  cover: true,    // 遮罩层可覆盖原生组件
})

5. TypeScript 类型错误

解决: 正确导入类型

typescript
import { useToast } from '@/wd'
import type { Toast, ToastOptions } from '@/wd'

const toast: Toast = useToast()
const options: ToastOptions = {
  msg: '类型安全的配置',
  duration: 3000,
  position: 'top',
}

总结

useToast 核心使用要点:

  1. 创建实例: const toast = useToast()useToast('selector')
  2. 显示提示: 根据场景选择 success/error/warning/info/loading
  3. 关闭 loading: 必须手动调用 toast.close()
  4. 页面配置: 必须放置 <wd-toast /> 组件
  5. 多实例隔离: 不同功能模块使用不同 selector