amis Toast 轻提示组件完全指南:JSON 配置、动作触发与源码原理
【免费下载链接】amis前端低代码框架,通过 JSON 配置就能生成各种页面。项目地址: https://gitcode.com/GitHub_Trending/am/amis
Toast(轻提示)是 amis 低代码框架中用于在页面短暂展示反馈信息的前端组件。它既可以直接作为按钮的actionType: "toast"动作使用,也可以在表单提交、接口请求失败等场景下由框架内部调用,帮助开发者在不跳转页面、不打断操作的前提下向用户传递成功、失败、警告等即时消息。阅读完本文,你将掌握 Toast 的完整配置项(位置、图标、关闭按钮、持续时间、HTML 渲染)、逐条消息的差异化设置,以及它背后的事件动作机制与单例渲染原理,可直接在 amis 页面 JSON 中落地使用。
Toast 轻提示组件是什么
在 amis 中,Toast 并不是一个需要主动放入页面 body 的"普通渲染组件",而是一种全局轻提示能力:通过按钮或事件动作触发后,提示消息会以浮层形式出现在屏幕指定位置,并在数秒后自动消失,整个过程不需要用户点击确认。
从实现层面看,Toast 由两部分协作完成:
- 动作声明:页面 JSON 中通过
actionType: "toast"声明触发方式,配合toast.items描述要展示的消息内容; - 渲染层:底层的 ToastComponent 以单例模式挂载(源码注释明确说明"单例模式,App 级别只需要一个 ToastComponent,引入了多个会兼容,也只有第一个生效"),所有 Toast 消息都通过它统一渲染和销毁。
在 amis-core 中,Toast 被注册为全局动作之一:ToastAction.ts 中的registerAction('toast', new ToastAction())使其可以被按钮动作或事件动作引用,最终调用env.notify(level, msg, config)完成消息弹出(见 packages/amis-core/src/actions/ToastAction.ts)。
基本用法:通过按钮动作触发
最常用的方式是将按钮的actionType指定为toast,并在toast.items中配置要展示的轻提示内容:
{ "label": "提示", "type": "button", "actionType": "toast", "toast": { "items": [ {"body": "轻提示内容"} ] } }点击按钮后,页面顶部中央会出现一条"轻提示内容"消息,默认展示类型图标,数秒后自动消失。一个页面中可以放置多个这样的按钮,各自配置独立的提示内容:
{ "type": "page", "body": [ { "label": "提示", "type": "button", "actionType": "toast", "toast": { "items": [ {"body": "轻提示内容"} ] } }, { "label": "提示2", "type": "button", "actionType": "toast", "toast": { "items": [ {"body": "轻提示内容2"} ] } } ] }设置提示位置(position)
通过toast.position可以控制轻提示出现的屏幕方位,支持 7 个可选值:
| 可选值 | 说明 |
|---|---|
top-left | 左上方 |
top-center | 上方居中(默认) |
top-right | 右上方 |
center | 屏幕正中间 |
bottom-left | 左下方 |
bottom-center | 下方居中 |
bottom-right | 右下方 |
{ "label": "提示", "type": "button", "actionType": "toast", "toast": { "position": "bottom-center", "items": [ {"body": "轻提示内容2"} ] } }需要注意:默认位置为top-center,移动端默认变为center(屏幕正中间)。这一逻辑在 Toast.tsx 中实现——当mobileUI开启且未显式指定position时,消息会被强制居中展示。
从源码看,多条 Toast 会按照各自的位置进行分组渲染:ToastComponent.render()使用groupBy(items, item => position)把同一方位的消息聚到同一个Toast-wrap容器中(见 packages/amis-ui/src/components/Toast.tsx),因此不同方向的提示互不干扰。
控制关闭按钮(closeButton)
默认情况下 Toast 不展示关闭按钮,消息到期自动消失。如需让用户手动关闭,可将closeButton设为true:
{ "label": "提示", "type": "button", "actionType": "toast", "toast": { "closeButton": true, "items": [ {"body": "轻提示内容"} ] } }设为false则明确不展示关闭按钮:
{ "label": "提示", "type": "button", "actionType": "toast", "toast": { "closeButton": false, "items": [ {"body": "轻提示内容"} ] } }实现细节上,是否展示关闭按钮在 Toast.tsx 中判断:closeButton={!mobileUI && (item.closeButton ?? closeButton)}——移动端一律不展示关闭按钮;PC 端若单条消息未单独配置,则继承外层toast.closeButton。另外,关闭按钮的展示与否还会影响点击行为:展示了关闭按钮时点击消息本体不会触发关闭,反之点击消息即可提前关闭(见 Toast.tsx 的onClick={closeButton ? noop : this.close})。
控制类型图标(showIcon)
Toast 会根据消息的level类型展示对应的图标(成功、错误、信息、警告各有不同图标)。若不需要图标,可将showIcon设为false:
{ "label": "提示", "type": "button", "actionType": "toast", "toast": { "showIcon": false, "items": [ {"body": "轻提示内容"} ] } }图标渲染逻辑位于 Toast.tsx:showIcon === false时整块图标区域不渲染;否则根据level值映射到success/fail/info/warning四个图标。类型图标还受到移动端样式的影响,移动端会附加Toast-mobile--has-icon类名以适配显示。
设置持续时间(timeout)
通过timeout可控制提示停留的毫秒数,单位是毫秒:
{ "label": "提示", "type": "button", "actionType": "toast", "toast": { "timeout": 1000, "items": [ {"body": "轻提示内容"} ] } }关于持续时间的默认值,官方属性表给出的规则为:默认 5000ms(error 类型为 6000ms,移动端为 3000ms)。源码中与之呼应的关键实现:
- ToastComponent 的 defaultProps 定义了
timeout: 4000、errorTimeout: 6000,并注释"错误的时候 time 调长"; - 实际计算在 Toast.tsx 第 224-225 行:
item.timeout ?? (level === 'error' ? errorTimeout : timeout),即单条消息未配置 timeout 时,error 类型使用更长的 6000ms,其余类型使用默认时长; - 移动端分支在 Toast.tsx 第 150 行 强制将 timeout 置为 3000ms。
无论配置多少时长,消息都会通过Transition组件配合 750ms 的过渡动画完成淡入淡出,鼠标悬停在消息上时计时会暂停(handleMouseEnter清除定时器),移开后重新计时(见 Toast.tsx)。
带标题的提示
每个 Toast 条目都可以通过title设置标题,配合body组成"标题 + 内容"的消息结构:
{ "label": "提示", "type": "button", "actionType": "toast", "toast": { "items": [ {"title": "标题", "body": "轻提示内容"} ] } }title与body的类型都是string | SchemaNode,既可以是纯文本字符串,也可以是 amis Schema 节点。渲染时标题会套用Toast-title类名、正文套用Toast-body类名(见 Toast.tsx),方便通过 CSS 定制样式。
每条提示单独设置不同类型(level)
level决定消息的类型与对应图标,支持info、success、error、warning四种取值。外层toast.items是一个数组,因此可以在一次触发中同时弹出多条不同类型的消息:
{ "label": "提示", "type": "button", "actionType": "toast", "toast": { "items": [ {"body": "普通消息提示", "level": "info"}, {"body": "成功消息提示", "level": "success"}, {"body": "错误消息提示", "level": "error"}, {"body": "警告消息提示", "level": "warning"} ] } }每条消息会依据自身的level渲染对应样式的Toast Toast--info/success/error/warning容器与图标(见 Toast.tsx)。需要说明的是,level的默认值为info(ToastMessage 的 defaultProps),未配置时按普通信息提示处理。
每条提示单独设置不同位置
除了在外层统一设置position,也可以为items中的每一条消息单独指定位置,实现"一次触发、多处弹出"的效果:
{ "label": "提示", "type": "button", "actionType": "toast", "toast": { "items": [ {"body": "左上方提示", "position": "top-left"}, {"body": "上方提示", "position": "top-center"}, {"body": "右上方提示", "position": "top-right"}, {"body": "中间提示", "position": "center"}, {"body": "左下方提示", "position": "bottom-left"}, {"body": "下方提示", "position": "bottom-center"}, {"body": "右上下方提示", "position": "bottom-right"} ] } }渲染层会优先使用每条消息自身的position,未配置时回退到外层toast.position(见 Toast.tsx 第 206 行 的groupBy(items, item => item.position || position))。
每条提示单独设置关闭按钮与持续时间
closeButton与timeout同样支持逐条覆盖:
{ "label": "提示", "type": "button", "actionType": "toast", "toast": { "items": [ {"body": "展示关闭按钮", "closeButton": true}, {"body": "不展示关闭按钮", "closeButton": false} ] } }{ "label": "提示", "type": "button", "actionType": "toast", "toast": { "items": [ {"body": "持续1秒", "timeout": 1000}, {"body": "持续3秒", "timeout": 3000} ] } }源码中这两项的逐条覆盖逻辑分别为item.closeButton ?? closeButton与item.timeout ?? (level === 'error' ? errorTimeout : timeout)(见 packages/amis-ui/src/components/Toast.tsx),即单条配置优先,未配置时继承外层默认值。这种"外层默认 + 单条覆盖"的设计让你既能批量统一风格,又能在个别场景下做差异化处理。
渲染 HTML 内容(allowHtml)
Toast 的body默认支持 HTML 片段渲染,allowHtml默认为true。因此可以直接传入带标签的内容:
{ "label": "提示", "type": "button", "actionType": "toast", "toast": { "items": [ {"body": "<strong>Hello</strong> <span>world</span>"} ] } }在渲染实现中,allowHtml为true时正文通过<Html html={...} />组件渲染,否则以纯文本方式输出(见 Toast.tsx)。如果你展示的是不可信内容,可以将allowHtml设为false避免被当作 HTML 解析。
属性表
Toast 动作属性(外层)
| 属性名 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| actionType | string | "toast" | 指定为 toast 轻提示组件 |
| items | Array<ToastItem> | [] | 轻提示内容 |
| position | string | top-center(移动端为center) | 提示显示位置,可用top-right、top-center、top-left、bottom-center、bottom-left、bottom-right、center |
| closeButton | boolean | false | 是否展示关闭按钮,移动端不展示 |
| showIcon | boolean | true | 是否展示图标 |
| timeout | number | 5000(error类型为6000,移动端为3000) | 持续时间 |
ToastItem 属性表(单条消息)
| 属性名 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| title | string \| SchemaNode | 无 | 标题 |
| body | string \| SchemaNode | 无 | 内容 |
| level | string | info | 展示图标,可选info、success、error、warning |
| position | string | top-center(移动端为center) | 提示显示位置,可选值同上 |
| closeButton | boolean | false | 是否展示关闭按钮 |
| showIcon | boolean | true | 是否展示图标 |
| timeout | number | 5000(error类型为6000,移动端为3000) | 持续时间 |
| allowHtml | boolean | true | 是否会被当作 HTML 片段处理 |
以上字段在类型层面与 amis-core 的 AMISToastBase 定义 一一对应,其中position与level在类型系统中被限定为枚举值,配置时若写错会在 TypeScript 校验阶段直接报错。
源码原理:从动作注册到单例渲染
1. 动作注册与 env.notify 调用链
ToastAction.ts 将toast注册为全局动作(registerAction('toast', new ToastAction()))。其run方法的核心逻辑是:
event.context.env?.notify?.( action.args?.msgType || 'info', String(action.args?.msg), {...action.args, mobileUI: renderer.props.mobileUI} );也就是说,toast动作最终统一走env.notify(level, msg, config)这条消息通道。这解释了为什么 amis 中大量内置逻辑(如表单提交失败、接口请求报错)都会以 Toast 形式弹出提示——它们都在内部调用了同一套env.notify(可参考 ChainedSelect.tsx、InputTable.tsx 等渲染器中的env.notify('error', ...)调用)。
2. 单例 ToastComponent 与编程式 API
packages/amis-ui/src/components/Toast.tsx 同时导出了组件与编程式调用入口:
export const toast = { container: toastRef, success: (content, conf) => show(content, conf, 'success'), error: (content, conf) => show(content, conf, 'error'), info: (content, conf) => show(content, conf, 'info'), warning: (content, conf) => show(content, conf, 'warning') };toastRef在ToastComponent挂载时被赋值,卸载时清空(见 Toast.tsx 第 123-132 行),从而保证全局只有一个生效实例;notifiy方法在移动端会清空已有 items("移动端只能存在一个"),并把默认位置改为center、超时改为 3000ms(见 Toast.tsx 第 134-157 行)。
3. 多条消息的分组与定时销毁
ToastComponent.render()按 position 分组渲染不同方向的容器;每条ToastMessage使用react-transition-group的Transition完成进出场动画,并在onEntered时启动setTimeout定时关闭,onMouseEnter暂停计时、onMouseLeave重新计时(见 Toast.tsx 第 310-334 行)。关闭按钮通过onClick={this.close}主动触发销毁,最终经onExited={onDismiss}从父组件状态中移除(Toast.tsx 第 353-360 行)。
总结
amis 的 Toast 轻提示组件以"按钮动作 + JSON 配置"的形式提供了轻量、灵活的消息反馈能力:items支持批量弹出多条消息,position/closeButton/showIcon/timeout/level/title/allowHtml既能在外层统一设置,也能在每条消息上单独覆盖;底层则由单例的ToastComponent统一渲染,配合env.notify事件通道与toast.success / error / info / warning编程式 API,可在任意页面逻辑中随时唤起提示。理解这套"动作声明 + 全局渲染"的机制后,你不仅能配置出各种形态的轻提示,还能在自己的 amis 扩展或事件动作中复用同一套消息能力。
【免费下载链接】amis前端低代码框架,通过 JSON 配置就能生成各种页面。项目地址: https://gitcode.com/GitHub_Trending/am/amis
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考