事件动作
1.7.0 及以上版本
上一节我们介绍了如何实现联动,是比较基础和局限的,而事件动作是更简单、更灵活、更高级的用法,可以解决复杂的 UI 交互场景,支持渲染器事件监听和响应设计,无需关心组件层级关系。例如:
- 传递数据
- 点击「按钮」,发送一个远程请求,返回的数据回填给一个表单
- 弹窗提交后,将弹窗内表单数据回填给另一个表单
- 联动刷新
- 下拉选择不同项,联动刷新表单数据
- 状态控制
- 勾选不同按钮,控制相应组件的显示/隐藏
- 勾选不同按钮,控制相应组件的启用/禁用
- 多个组件监听同一个事件做出不同响应
- 下拉选择不同项,组件 A 监听后发送一个远程请求,组件 B 监听后进行刷新
- 逻辑编排
- 针对监听到的事件,循环执行一些动作作为响应,还可以控制循环跳出或跳过
- 针对监听到的事件,根据条件选择性的执行动作响应
- 针对监听到的事件,并行执行多个动作作为响应
- 执行完当前动作后,可以选择是否继续执行后续动作,是否关闭事件默认行为的执行
基本使用
通过onEvent属性实现渲染器事件与响应动作的绑定。onEvent内配置事件和动作映射关系,actions是事件对应的响应动作的集合。
{type: 'page',body: [{type: 'button',label: '尝试点击、鼠标移入/移出',level: 'primary',onEvent: {click: {actions: [{actionType: 'toast',args: {msgType: 'info',msg: '派发点击事件'}}]},mouseenter: {actions: [{actionType: 'toast',args: {msgType: 'info',msg: '派发鼠标移入事件'}}]},mouseleave: {actions: [{actionType: 'toast',args: {msgType: 'info',msg: '派发鼠标移出事件'}}]}}}]}
事件与动作
事件包含渲染器事件和广播事件,监听这些事件时,可以通过event.data来获取事件对象的数据。
- 渲染器事件,由具体的渲染器组件提供,每个渲染器组件暴露的事件可以查看具体的组件文档的事件表;
- 广播事件,即自定义事件,可以自定义派发的事件名称
eventName,其他渲染器可以监听该自定义事件并配置响应动作。
动作包含通用动作、组件动作、广播动作、自定义动作,可以通过配置actionType来指定具体执行什么动作。
触发通用动作
通用动作包含发送 http 请求、跳转链接、浏览器回退、浏览器刷新、打开/关闭弹窗、打开/关闭抽屉、打开对话框、弹出 Toast 提示、复制、发送邮件、刷新、控制显示隐藏、控制启用禁用状态、更新数据。
发送 http 请求
通过配置actionType: 'ajax'和api实现 http 请求发送,该动作需实现 env.fetcher(config: fetcherConfig) => Promise<fetcherResult>。
{type: 'page',data: {name: 'lll'},body: [{type: 'button',id: 'b_001',label: '发送 Ajax 请求',level: 'primary',"confirmText": "确认要发出这个请求?",onEvent: {click: {actions: [{actionType: 'ajax',args: {api: {url: 'https://3xsw4ap8wah59.cfc-execute.bj.baidubce.com/api/amis-mock/mock2/form/saveForm?name=${name}',method: 'get'},messages: {success: '成功了!欧耶',failed: '失败了呢。。'},age: 18}}]}}}]}
动作属性
| 属性名 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| actionType | string |
ajax |
ajax 请求 |
| args.api | API | - | 接口配置,< 1.8.0 及以下版本 为 api |
| args.options | object |
- | 其他配置,< 1.8.0 及以下版本 为 options |
| args.messages | {success: string, failed: string} |
- | 请求成功/失败后的提示信息,< 1.8.0 及以下版本 为 messages |
打开弹窗(模态)
通过配置actionType: 'dialog'和dialog实现 Dialog 弹窗。
{type: 'page',body: [{type: 'button',className: 'ml-2',label: '打开弹窗(模态)',level: 'primary',onEvent: {click: {actions: [{actionType: 'dialog',dialog: {type: 'dialog',title: '模态弹窗',id: 'dialog_001',data: {myage: '22'},body: [{type: 'tpl',tpl: '<p>对,你打开了模态弹窗</p>',inline: false},{type: 'input-text',name: 'myname',mode: 'horizontal',onEvent: {change: {actions: [{actionType: 'confirm',componentId: 'dialog_001'}]}}}],onEvent: {confirm: {actions: [{actionType: 'toast',args: {msg: 'confirm'}}]},cancel: {actions: [{actionType: 'toast',args: {msg: 'cancel'}}]}}}}]}}}]}
动作属性
| 属性名 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| actionType | string |
dialog |
点击后显示一个弹出框 |
| dialog | string/DialogObject |
- | 指定弹框内容,格式可参考Dialog |
关闭弹窗(模态)
通过配置actionType: 'closeDialog'实现关闭当前弹窗;附加配置componentId可以实现关闭指定弹窗。
{type: 'page',body: [{type: 'button',id: 'b_003',label: '打开弹窗(模态)',level: 'primary',onEvent: {click: {actions: [{actionType: 'dialog',dialog: {type: 'dialog',id: 'dialog_002',title: '模态弹窗',body: [{type: 'button',label: '打开子弹窗,然后关闭它的父亲',onEvent: {click: {actions: [{actionType: 'dialog',dialog: {type: 'dialog',title: '模态子弹窗',body: [{type: 'button',label: '关闭指定弹窗(关闭父弹窗)',onEvent: {click: {actions: [{actionType: 'closeDialog',componentId: 'dialog_002'}]}}}]}}]}}},{type: 'button',label: '关闭当前弹窗',className: 'ml-2',onEvent: {click: {actions: [{actionType: 'closeDialog'}]}}}]}}]}}}]}
动作属性
| 属性名 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| actionType | string |
closeDialog |
关闭弹窗 |
| componentId | string |
- | 指定弹框组件 id |
打开抽屉(模态)
通过配置actionType: 'drawer'和drawer实现 Drawer 抽屉打开。
{type: 'page',body: [{type: 'button',id: 'b_004',level: 'primary',label: '打开抽屉(模态)',onEvent: {click: {actions: [{actionType: 'drawer',drawer: {type: 'drawer',title: '模态抽屉',body: [{type: 'tpl',tpl: '<p>对,你打开了模态抽屉</p>',inline: false}],onEvent: {confirm: {actions: [{actionType: 'toast',args: {msg: 'confirm'}}]},cancel: {actions: [{actionType: 'toast',args: {msg: 'cancel'}}]}}}}]}}}]}
动作属性
| 属性名 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| actionType | string |
drawer |
点击后显示一个侧边栏 |
| drawer | string/DrawerObject |
- | 指定弹框内容,格式可参考Drawer |
关闭抽屉(模态)
通过配置actionType: 'closeDrawer'实现关闭当前抽屉;附加配置componentId可以实现关闭指定抽屉。
{type: 'page',body: [{type: 'button',label: '打开抽屉(模态)',level: 'primary',onEvent: {click: {actions: [{actionType: 'drawer',drawer: {type: 'drawer',id: 'drawer_1',title: '模态抽屉',body: [{type: 'button',label: '打开子抽屉,然后关闭它的父亲',onEvent: {click: {actions: [{actionType: 'drawer',drawer: {type: 'drawer',title: '模态子抽屉',body: [{type: 'button',label: '关闭指定抽屉(关闭父抽屉)',onEvent: {click: {actions: [{actionType: 'closeDrawer',componentId: 'drawer_1'}]}}}]}}]}}},{type: 'button',label: '关闭当前抽屉',className: 'ml-2',onEvent: {click: {actions: [{actionType: 'closeDrawer'}]}}}]}}]}}}]}
动作属性
| 属性名 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| actionType | string |
closeDrawer |
关闭抽屉 |
| componentId | string |
- | 指定抽屉组件 id |
打开对话框
通过配置actionType: 'alert'或actionType: 'confirm'打开不同对话框,该动作分别需实现 env.alert: (msg: string) => void 和 env.confirm: (msg: string, title?: string) => boolean | Promise<boolean>。
提示对话框
{type: 'page',data: {msg: '去吃饭了'},body: [{type: 'button',label: '提示对话框(模态)',level: 'primary',onEvent: {click: {actions: [{actionType: 'alert',args: {msg: '<a href="http://www.baidu.com" target="_blank">${msg}~</a>'}}]}}}]}
动作属性
| 属性名 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| actionType | string |
alert |
打开提示对话框 |
| args.msg | string |
- | 对话框提示内容,< 1.8.0 及以下版本 为 msg |
确认对话框
{type: 'page',data: {title: '操作确认',msg: '要删除它吗?'},body: [{type: 'button',label: '确认对话框(模态)',level: 'primary',onEvent: {click: {actions: [{actionType: 'confirmDialog',args: {title: '${title}',msg: '<span style="color:red">${msg}</span>'}}]}}}]}
动作属性
| 属性名 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| actionType | string |
confirmDialog |
打开确认对话框 |
| args.title | string |
- | 对话框标题,< 1.8.0 及以下版本 为 title |
| args.msg | string |
- | 对话框提示内容,< 1.8.0 及以下版本 为 msg |
跳转链接
通过配置actionType: 'url'或actionType: 'link'实现链接跳转,该动作需实现 env.jumpTo(to: string, action?: any) => void 方法。
打开页面链接
{type: 'page',data: {myname: 'lvxj',myjon: 'player'},body: [{type: 'button',label: '百度一下',level: 'primary',className: 'ml-2',onEvent: {click: {actions: [{actionType: 'url',args: {url: 'http://www.baidu.com',blank: true,params: {name: 'jack',jon: '${myjon}'},name: '${myname}',age: 18}}]}}}]}
动作属性
| 属性名 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| actionType | string |
url |
页面跳转 |
| args.url | string |
- | 按钮点击后,会打开指定页面。可用 ${xxx} 取值,< 1.8.0 及以下版本 为 url |
| args.blank | boolean |
false |
如果为 true 将在新 tab 页面打开,< 1.8.0 及以下版本 为 blank |
| args.params | object |
- | 页面参数{key:value},支持数据映射,> 1.10.0 及以上版本 |
打开单页链接
{type: 'page',body: [{type: 'button',label: '跳转至「表达式」',level: 'primary',className: 'ml-2',onEvent: {click: {actions: [{actionType: 'link',args: {link: './expression'}}]}}}]}
动作属性
| 属性名 | 类型 | 默认值 | 说明 |
| ————— | ———— | ——— | —————————————————————————————————————————————————————————- |
| actionType | string | link | 单页跳转 |
| args.link | string | link | 用来指定跳转地址,跟 url 不同的是,这是单页跳转方式,不会渲染浏览器,请指定 amis 平台内的页面。可用 ${xxx} 取值,< 1.8.0 及以下版本 为 link |
| args.params | object | - | 页面参数{key:value},支持数据映射,> 1.9.0 及以上版本 |
浏览器回退
1.8.0 及以上版本
通过配置actionType: 'goBack'实现页面回退。
{type: 'page',body: [{type: 'button',label: '回退',level: 'primary',className: 'ml-2',onEvent: {click: {actions: [{actionType: 'goBack'}]}}}]}
动作属性
| 属性名 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| actionType | string |
goBack |
返回上个页面 |
前进/后退到指定页面
1.8.0 及以上版本
通过配置actionType: 'goPage'实现浏览器页面的前进/后退。
{type: 'page',body: [{type: 'button',label: '后退到上上个页面',level: 'primary',className: 'ml-2',onEvent: {click: {actions: [{actionType: 'goPage',delta: -2}]}}}]}
动作属性
| 属性名 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| actionType | string |
goPage |
前进/后退到页面 |
| args.delta | string |
0 |
位置,< 1.8.0 及以下版本 为 delta |
浏览器刷新
1.8.0 及以上版本
通过配置actionType: 'refresh'实现浏览器刷新。
{type: 'page',body: [{type: 'button',label: '刷新页面',level: 'primary',className: 'ml-2',onEvent: {click: {actions: [{actionType: 'refresh'}]}}}]}
动作属性
| 属性名 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| actionType | string |
refresh |
返回上个页面 |
toast 提示
通过配置actionType: 'toast'和msg实现弹出 toast 提示,该动作需实现 env.notify(type: ToastLevel, msg: string, conf?: ToastConf) => void 方法。
{type: 'page',body: [{type: 'button',label: '警告',level: 'warning',className: 'mr-2 mb-2',onEvent: {click: {actions: [{actionType: 'toast',args: {msgType: 'warning',msg: '我是全局警告消息,可以配置不同类型和弹出位置~',position: 'top-right'}}]}}},{type: 'button',label: '成功',level: 'success',className: 'mr-2 mb-2',onEvent: {click: {actions: [{actionType: 'toast',args: {msgType: 'success',msg: '我是全局警告消息,可以配置不同类型和弹出位置~',position: 'top-right'}}]}}},{type: 'button',label: '错误',level: 'danger',className: 'mr-2 mb-2',onEvent: {click: {actions: [{actionType: 'toast',args: {msgType: 'error',msg: '我是全局警告消息,可以配置不同类型和弹出位置~',position: 'top-right'}}]}}},{type: 'button',label: '提示',level: 'info',className: 'mb-2',onEvent: {click: {actions: [{actionType: 'toast',args: {msgType: 'info',msg: '我是全局警告消息,可以配置不同类型和弹出位置~',position: 'top-right'}}]}}},{type: 'tpl',tpl: '<br>',},{type: 'button',label: '左上',className: 'mr-2 mt-2',onEvent: {click: {actions: [{actionType: 'toast',args: {msgType: 'info',msg: '我是全局警告消息,可以配置不同类型和弹出位置~',position: 'top-left'}}]}}},{type: 'button',label: '中上',className: 'mr-2 mt-2',onEvent: {click: {actions: [{actionType: 'toast',args: {msgType: 'info',msg: '我是全局警告消息,可以配置不同类型和弹出位置~',position: 'top-center'}}]}}},{type: 'button',label: '右上',className: 'mt-2',onEvent: {click: {actions: [{actionType: 'toast',args: {msgType: 'info',msg: '我是全局警告消息,可以配置不同类型和弹出位置~',position: 'top-right'}}]}}},{type: 'tpl',tpl: '<br>',},{type: 'button',label: '屏幕的中央',className: 'ml-10 mt-2 mb-2',onEvent: {click: {actions: [{actionType: 'toast',args: {msgType: 'info',msg: '我是全局警告消息,可以配置不同类型和弹出位置~',position: 'center'}}]}}},{type: 'tpl',tpl: '<br>',},{type: 'button',label: '左下',className: 'mr-2',onEvent: {click: {actions: [{actionType: 'toast',args: {msgType: 'info',msg: '我是全局警告消息,可以配置不同类型和弹出位置~',position: 'bottom-left'}}]}}},{type: 'button',label: '中下',className: 'mr-2',onEvent: {click: {actions: [{actionType: 'toast',args: {msgType: 'info',msg: '我是全局警告消息,可以配置不同类型和弹出位置~',position: 'bottom-center'}}]}}},{type: 'button',label: '右下',onEvent: {click: {actions: [{actionType: 'toast',args: {msgType: 'info',msg: '我是全局警告消息,可以配置不同类型和弹出位置~',position: 'bottom-right'}}]}}}]}
动作属性
| 属性名 | 类型 | 默认值 | 说明 | ||||||
|---|---|---|---|---|---|---|---|---|---|
| actionType | string |
"toast" |
指定 toast 动作 | ||||||
| args.msgType | string |
"info" |
消息类型 `info\ | success\ | error\ | warning,< 1.8.0 及以下版本 为 msgType` |
|||
| args.msg | string |
- | 消息内容,< 1.8.0 及以下版本 为 msg |
||||||
| args.position | string |
top-center(移动端为center) |
提示显示位置 `top-right\ | top-center\ | top-left\ | bottom-center\ | bottom-left\ | bottom-right\ | center,< 1.8.0 及以下版本 为 position` |
| args.closeButton | boolean |
false |
是否展示关闭按钮,< 1.8.0 及以下版本 为 closeButton |
||||||
| args.showIcon | boolean |
true |
是否展示图标,< 1.8.0 及以下版本 为 showIcon |
||||||
| args.timeout | number |
5000(error类型为6000,移动端为3000) |
持续时间,< 1.8.0 及以下版本 为 timeout |
复制
通过配置actionType: 'copy'和复制属性实现文本的复制操作,该动作需实现 env.copy(contents: string, options?: any) => void 方法。
{type: 'page',body: [{type: 'button',label: '复制一段文本',level: 'primary',className: 'mr-2',onEvent: {click: {actions: [{actionType: 'copy',args: {content: 'http://www.baidu.com'}}]}}},{type: 'button',label: '复制一段富文本',level: 'primary',onEvent: {click: {actions: [{actionType: 'copy',args: {copyFormat: 'text/html',content: "<a href='http://www.baidu.com'>link</a> <b>bold</b>"}}]}}}]}
动作属性
| 属性名 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| actionType | string |
copy |
复制一段内容到粘贴板 |
| args.copyFormat | string |
text/html |
复制格式,< 1.8.0 及以下版本 为 copyFormat |
| args.content | 模板 | - | 指定复制的内容。可用 ${xxx} 取值,< 1.8.0 及以下版本 为 content |
发送邮件
通过配置actionType: 'email'和邮件属性实现发送邮件操作。
{type: 'page',body: [{type: 'button',label: '发送邮件',level: 'primary',onEvent: {click: {actions: [{actionType: 'email',args: {to: 'amis@baidu.com',cc: 'baidu@baidu.com',subject: '这是邮件主题',body: '这是邮件正文'}}]}}}]}
动作属性
| 属性名 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| actionType | string |
email |
点击后显示一个弹出框 |
| args.to | string |
- | 收件人邮箱,可用 ${xxx} 取值,< 1.8.0 及以下版本 为 to |
| args.cc | string |
- | 抄送邮箱,可用 ${xxx} 取值,< 1.8.0 及以下版本 为 cc |
| args.bcc | string |
- | 匿名抄送邮箱,可用 ${xxx} 取值,< 1.8.0 及以下版本 为 bcc |
| args.subject | string |
- | 邮件主题,可用 ${xxx} 取值,< 1.8.0 及以下版本 为 subject |
| args.body | string |
- | 邮件正文,可用 ${xxx} 取值,< 1.8.0 及以下版本 为 body |
刷新
通过配置actionType: 'reload'实现对指定组件的刷新(重新加载)操作,仅支持form、wizard、service、page、app、chart、crud,以及支持动态数据的输入类组件,详见组件的动作表。更多示例请查看刷新示例。
{type: 'page',body: [{type: 'button',label: '刷新',className: 'mb-2',level: 'primary',onEvent: {click: {actions: [{actionType: 'reload',componentId: 'form-reload'}]}}},{type: 'form',id: 'form-reload',name: 'form-reload',initApi:'https://3xsw4ap8wah59.cfc-execute.bj.baidubce.com/api/amis-mock/mock2/page/initData',title: '表单',body: [{type: 'input-text',id: 'date-input-01',name: 'date',label: '时间戳'}]}]}
动作属性
| 属性名 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| actionType | string |
reload |
刷新组件 |
| componentId | string |
- | 指定刷新的目标组件 id |
显示与隐藏
1.8.0 及以上版本
通过配置actionType: 'show'或'hidden'实现对指定组件的显示和隐藏,且显隐动作的控制高于组件显隐属性的设置。
{type: 'page',body: [{type: 'button',label: '显示',level: 'primary',className: 'mr-2',onEvent: {click: {actions: [{actionType: 'show',componentId: 'input-text_001'}]}}},{type: 'button',label: '隐藏',level: 'primary',onEvent: {click: {actions: [{actionType: 'hidden',componentId: 'input-text_001'}]}}},{type: 'input-text',label: '愿望',className: 'mt-2',id: 'input-text_001',mode: 'horizontal',hidden: true}]}
动作属性
| 属性名 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| actionType | string |
show or hidden |
显示或隐藏组件 |
| componentId | string |
- | 指定显示或隐藏的目标组件 id |
控制状态
1.8.0 及以上版本
通过配置actionType: 'enabled'或actionType: 'disabled'实现对指定组件的启用和禁用,仅支持实现了状态控制功能的数据输入类组件。
{type: 'page',body: [{type: 'button',id: 'b_dis',label: '禁用',level: 'primary',className: 'mr-2 mb-2',disabled: true,onEvent: {click: {actions: [{actionType: 'disabled',componentId: 'form_disable'}]}}},{type: 'button',label: '启用',level: 'primary',className: 'mb-2',onEvent: {click: {actions: [{actionType: 'enabled',componentId: 'form_disable'}]}}},{type: 'form',id: 'form_disable',title: '表单',body: [{type: 'group',body: [{type: 'button',className: 'ml-2',label: '我的状态变了'},{type: 'button',className: 'ml-2',label: '禁用上面的按钮',level: 'primary',onEvent: {click: {actions: [{actionType: 'disabled',componentId: 'b_dis'}]}}},{type: 'button',className: 'ml-2',label: '启用用上面的按钮',level: 'primary',onEvent: {click: {actions: [{actionType: 'enabled',componentId: 'b_dis'}]}}}]}]}]}
动作属性
| 属性名 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| actionType | string |
enabled or disabled |
启用或禁用组件 |
| componentId | string |
- | 指定启用或禁用的目标组件 id |
更新数据
1.8.0 及以上版本
更新数据即变量赋值,通过配置actionType: 'setValue'实现组件数据域变量更新,通过它可以实现组件间联动更新、数据回填,支持基础类型、对象类型、数组类型,数据类型取决于目标组件所需数据值类型,仅支持form、dialog、drawer、wizard、service、page、app、chart,以及数据输入类组件。更多示例请查看更新数据示例。
{type: 'page',title: '更新表单数据',data: {globalData: {myrole: '法官',mymsg: '该吃饭了!'}},body: [{type: 'button',label: '更新',level: 'primary',className: 'mb-2',onEvent: {click: {actions: [{actionType: 'setValue',componentId: 'form_data',args: {value: '${globalData}'}}]}}},{type: 'form',id: 'form_data',title: '表单',debug: true,data: {myrole: '预言家',age: '18'},"initApi": "/api/mock2/form/initData",body: [{type: 'input-text',label: '角色',name: 'myrole',disabled: false,mode: 'horizontal'},{type: 'input-text',label: '年龄',name: 'age',disabled: false,mode: 'horizontal'}]}]}
动作属性
| 属性名 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| actionType | string |
setValue |
变量赋值,即设置组件的数据值 |
| componentId | string |
- | 指定赋值的目标组件 id |
| args.value | any |
- | 值,< 1.8.0 及以下版本 为 value |
自定义 JS
通过配置actionType: 'custom'实现自定义 JS。
{type: 'page',body: [{type: 'button',label: '发送一个 http 请求',level: 'primary',onEvent: {click: {actions: [{actionType: 'custom',script:"doAction({actionType: 'ajax', args: {api: '/api/mock2/form/saveForm'}});\n //event.stopPropagation();"}]}}}]}
如果是在 js 中也能直接写函数,这个函数可以接收到 3 个参数,分别是:
- context,上下文信息
- doAction 方法,用于调用其它动作
- event,事件传递的数据,以及可以禁止
动作属性
| 属性名 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| actionType | string |
custom |
自定义 JS |
| script | string/function |
- | 自定义 JS 脚本代码,代码内可以通过调用doAction执行任何动作 ,通过事件对象event可以实现事件动作干预 |
触发其他组件的动作
通过配置componentId来触发指定组件的动作,组件动作配置通过args传入(> 1.9.0 及以上版本),动作参数请查看对应的组件的动作表,更多示例请查看组件事件动作示例。
{type: 'page',body: [{type: 'button',label: '选中选项卡2',level: 'primary',className: 'mr-3 mb-3',onEvent: {click: {actions: [{actionType: 'changeActiveKey',componentId: 'tabs-change-receiver',args: {activeKey: 2}}]}}},{id: 'tabs-change-receiver',type: 'tabs',mode: 'line',tabs: [{title: '选项卡1',body: '选项卡内容1'},{title: '选项卡2',body: '选项卡内容2'},{title: '选项卡3',body: '选项卡内容3'}]}]}
触发广播动作
通过配置actionType: 'broadcast'和eventName实现触发一个广播,可以通过配置动作执行优先级weight来控制所有监听者的动作执行顺序。
{type: 'page',body: [{"name": "role","type": "select","label": "广播一下","mode": "row","options": [{"label": "海贼王的男人","value": "路飞"},{"label": "海上华佗","value": "乔巴"},{"label": "海上食神","value": "山治"}],"onEvent": {"change": {"actions": [{actionType: 'broadcast',eventName: 'broadcast_1',args: {myrole: '${role}',age: 18}}]}}},{type: 'form',id: 'form_001_form_01',title: '表单1(优先级低)',name: 'sub-form1',body: [{type: 'input-text',label: '昵称',name: 'myname',disabled: false,mode: 'horizontal'}],onEvent: {broadcast_1: {actions: [{actionType: 'reload',args: {myname: '${event.data.value}', // 从事件数据中取}},{"actionType": "toast",args: {"msgType": "info","msg": "表单1刷新完成"}}]}}},{type: 'form',name: 'form2',id: 'form_002',title: '表单2(优先级中)',body: [{type: 'input-text',label: '角色',name: 'myrole',disabled: false,mode: 'horizontal'},{type: 'input-text',label: '年龄',name: 'age',disabled: false,mode: 'horizontal'}],onEvent: {broadcast_1: {weight: 2,actions: [{actionType: 'reload',args: {myrole: '${event.data.value}',age: '${event.data.age}'}},{"actionType": "toast",args: {"msgType": "info","msg": "表单2刷新完成"}}]}}},{type: 'form',name: 'form3',id: 'form_003',title: '表单3(优先级高)',body: [{type: 'input-text',id: 'form_003_text_01',label: '职业',name: 'job',disabled: false,mode: 'horizontal'}],api: 'https://api/form/form3',onEvent: {broadcast_1: {weight: 3,actions: [{actionType: 'reload',args: {job: '${event.data.value}'}},{"actionType": "toast",args: {"msgType": "info","msg": "表单3刷新完成"}}]}}}]}
动作属性
| 属性名 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| actionType | string |
broadcast |
广播动作 |
| eventName | string |
- | 广播动作对应的自定义事件名称,用于广播事件的监听 |
自定义动作
除了以上内置动作,你还可以注册自己的动作。通过对RendererAction的run方法的实现可以定制自己的动作逻辑,最后通过registerAction注册到 amis 事件动作中。
import {ListenerAction,ListenerContext,registerAction,RendererAction} from 'amis-core';import {RendererEvent} from 'amis-core';// 动作定义interface IMyAction extends ListenerAction {actionType: 'my-action';args: {param1: string, // 动作参数1param2: string // 动作参数2};}/*** 我的动作实现*/export class MyAction implements RendererAction {run(action: IMyAction, renderer: ListenerContext, event: RendererEvent<any>) {const props = renderer.props;const {param1, param2} = action.args;// 你的动作逻辑// ...}}// 注册自定义动作registerAction('my-action', new MyAction());
编排动作
通过配置actionType: 'for'或actionType: 'break'或actionType: 'continue'或actionType: 'switch'或actionType: 'parallel'实现动作的逻辑编排,支持嵌套。
条件
{type: 'page',body: {type: 'form',wrapWithPanel: false,data: {expression: 'okk'},body: [{type: 'button',label: '符合条件的执行',level: 'primary',onEvent: {click: {actions: [{actionType: 'toast',args: {msgType: 'success',msg: '我okk~'},expression: 'expression === "okk"'},{actionType: 'toast',args: {msg: '1'},expression: 'expression === "nono"'},{actionType: 'toast',args: {msgType: 'success',msg: '我也okk~'},expression: 'expression === "okk"'}]}}}]}}
动作属性
| 属性名 | 类型 | 默认值 | 说明 | |
|---|---|---|---|---|
| actionType | string |
for |
循环执行动作 | |
| expression | boolean\ |
表达式 | - | 执行条件,不设置表示默认执行 |
循环
单层循环
{type: 'page',body: {type: 'form',wrapWithPanel: false,data: {loopName: 'loopData',loopData: [{name: 'lv',age: '19'},{name: 'xj',age: '21'}]},body: [{type: 'button',label: '循环发送两次请求,且每次携带了循环的数据',level: 'primary',onEvent: {click: {actions: [{actionType: 'loop',args: {level: 3,loopName: '${loopName}'},children: [{actionType: 'ajax',args: {api: 'https://3xsw4ap8wah59.cfc-execute.bj.baidubce.com/api/amis-mock/mock2/form/saveForm?name=${name}&age=${age}'}}]}]}}}]}}
嵌套循环
{type: 'page',body: {type: 'form',wrapWithPanel: false,data: {loopName: 'loopData',loopData: [{name: 'lv',age: '19'},{name: 'xj',age: '21'}]},body: [{type: 'button',label: '循环',className: 'm-2',onEvent: {click: {actions: [{actionType: 'loop',preventDefault: false,stopPropagation: false,args: {loopName: '${loopName}',level: 3},children: [{actionType: 'toast',args: {msg: '第1层循环动作1${name}'},preventDefault: false,stopPropagation: false},{actionType: 'toast',args: {msg: '第1层循环动作2${name}'}},{actionType: 'loop',args: {loopName: '${loopName}',level: 3},children: [{actionType: 'toast',args: {msg: '第2层循环动作1${name}'}},{actionType: 'toast',args: {msg: '第2层循环动作2${name}'},preventDefault: false,stopPropagation: false},{actionType: 'continue'},{actionType: 'toast',args: {msg: '第2层循环动作3${name}'}}]}]}]}}}]}}
动作属性
| 属性名 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| actionType | string |
for |
循环执行动作 |
| args.loopName | string |
- | 循环变量名称,< 1.8.0 及以下版本 为 loopName |
| children | Array<动作> | - | 子动作,可以通过break动作来跳出循环 |
Break 动作
{type: 'page',body: {type: 'form',wrapWithPanel: false,data: {loopName: 'loopData',loopData: [{name: 'lv',age: '19'},{name: 'xj',age: '21'}]},body: [{type: 'button',label: '只执行了第一个动作就跳出了循环',level: 'primary',onEvent: {click: {actions: [{actionType: 'loop',args: {loopName: '${loopName}'},children: [{actionType: "toast",args: {msgType: 'success',msg: '第 1 个动作',position: 'top-right'}},{actionType: 'break'},{actionType: "toast",args: {msgType: 'success',msg: '第 2 个动作',position: 'top-right'}}]}]}}}]}}
动作属性
| 属性名 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| actionType | string |
break |
跳出循环动作 |
Continue 动作
{type: 'page',body: {type: 'form',wrapWithPanel: false,data: {loopName: 'loopData',loopData: [{name: 'lv',age: '19'},{name: 'xj',age: '21'}]},body: [{type: 'button',label: '只循环执行第一个动作',level: 'primary',onEvent: {click: {actions: [{actionType: 'loop',args: {loopName: '${loopName}',level: 3},children: [{actionType: "toast",args: {msgType: 'success',msg: '第 1 个动作',position: 'top-right'}},{actionType: 'continue'},{actionType: "toast",args: {msgType: 'success',msg: '最后的动作',position: 'top-right'}}]}]}}}]}}
动作属性
| 属性名 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| actionType | string |
continue |
跳出当前 |
排他(switch)
{type: 'page',body: {type: 'form',wrapWithPanel: false,data: {branchCont: 18},body: [{type: 'button',label: '只执行动作2',level: 'primary',onEvent: {click: {actions: [{actionType: 'switch',children: [{actionType: "toast",args: {msgType: 'info',msg: '动作1',position: 'top-right'},expression: 'this.branchCont > 19',stopPropagation: true // 这里无效,因为条件不成立},{actionType: "toast",args: {msgType: 'info',msg: '动作2',position: 'top-right'},expression: 'this.branchCont > 17'},{actionType: "toast",args: {msgType: 'info',msg: '动作3',position: 'top-right'},expression: 'this.branchCont > 16'}]}]}}}]}}
动作属性
| 属性名 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| actionType | string |
switch |
只执行第一个符合条件的动作 |
| children | Array<动作> | - | 子动作,每个子动作可以通过配置expression来匹配的条件 |
并行
{type: 'page',body: {type: 'form',wrapWithPanel: false,body: [{type: 'button',label: '同时发送两个ajax请求,并显示请求返回',level: 'primary',onEvent: {click: {actions: [{actionType: 'parallel',children: [{actionType: 'ajax',args: {api: {url: 'https://3xsw4ap8wah59.cfc-execute.bj.baidubce.com/api/amis-mock/mock2/form/initData?name=${name}',method: 'get'},messages: {success: '请求1成功了!欧耶',failed: '失败了呢。。'}},outputVar: 'var1'},{actionType: 'ajax',args: {api: {url: 'https://3xsw4ap8wah59.cfc-execute.bj.baidubce.com/api/amis-mock/mock2/form/saveForm?name=${name}',method: 'get'},messages: {success: '请求2成功了!欧耶',failed: '失败了呢。。'}},outputVar: 'var2'}]},{actionType: 'toast',args: {msg: 'var1:${event.data.var1|json}, var2:${event.data.var2|json}'}}]}}}]}}
动作属性
| 属性名 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| actionType | string |
parallel |
并行执行多个动作 |
| children | Array<动作> | - | 子动作 |
动作间数据传递
从事件触发开始,整个数据流包含事件本身产生的事件数据和动作产生的动作数据,事件源头产生的数据在 AMIS 事件动作机制底层已经自动加入渲染器数据域,可以通过event.data.xxx直接获取,而部分动作产生的数据如何流动需要交互设计者进行介入,对于数据流动可以通过数据映射,将上一个动作产生的数据作为动作参数写入下一个动作。
传递数据
通过 args 指定输入的参数数据,它是一个键值对。
{type: 'page',body: [{type: 'button',id: 'b_001',label: '发一个广播,携带动作参数',className: 'mb-2',level: 'primary',onEvent: {click: {actions: [{actionType: 'broadcast',eventName: 'broadcast_1',args: {name: 'lvxj',age: 18},description: '一个按钮的点击事件'}]}}},{type: 'form',name: 'form1',id: 'form_001',title: '接收广播事件的参数',debug: true,body: [{type: 'input-text',id: 'form_001_text_01',label: '年龄',name: 'age',disabled: false,mode: 'horizontal'}],data: {name: 'amis'},onEvent: {broadcast_1: {actions: [{actionType: 'reload',args: {age: '${event.data.age}'}}]}}}]}
存储异步请求返回的数据
通过 outputVar 指定输出的变量名,其他动作可以通过${event.data.{{outputVar}}}来获取变量值,如果未指定 outputVar ,则直接存储到event.data。
{type: 'page',body: [{type: 'button',label: '发送Ajax请求,并把返回数据传给弹窗',level: 'primary',onEvent: {click: {actions: [{actionType: 'ajax',args: {api: 'https://3xsw4ap8wah59.cfc-execute.bj.baidubce.com/api/amis-mock/mock2/form/saveForm',messages: {success: '成功了!欧耶',failed: '失败了呢。。'}},outputVar: 'ajax1'},{actionType: 'dialog',args: {id: '${event.data.ajax1.id}'},dialog: {type: 'dialog',id: 'dialog_005',title: '弹框标题1',data: {id: '${id}'},body: [{type: 'form',body: [{type: 'tpl',tpl: '<p>请求返回的数据:id=${id}</p>',inline: false}]}]}}]}}}]}
事件动作干预
事件动作干预是指执行完当前动作后,干预所监听事件默认处理逻辑和后续其他动作的执行。通过preventDefault、stopPropagation分别阻止监听事件默认行为和停止下一个动作执行。
阻止事件默认行为
有些组件内置了一些逻辑来帮助用户降低配置成本,但可能这些逻辑并不符合设计者的业务需求,这时可以通过onEvent来监听对应的事件,并通过preventDefault来阻止那些默认处理逻辑来达到想要的最终效果。更多示例请查看阻止组件默认行为示例。
{type: 'page',title: '弹窗确认后执行其他动作并阻止默认关闭',body: [{type: 'button',className: 'ml-2',label: '打开弹窗',level: 'primary',onEvent: {click: {actions: [{actionType: 'dialog',dialog: {type: 'dialog',title: '提示',id: 'dialog_001',data: {myage: '22'},body: [{type: 'alert',body: '输入Do not close,确认后将不关闭弹窗',level: 'warning'},{type: 'input-text',name: 'command'}],onEvent: {confirm: {actions: [{actionType: 'toast',args: {msg: '不关闭'},preventDefault: 'event.data.command === "Do not close"'}]}}}}]}}}]}
停止后续动作执行
通过onEvent可以对监听的事件配置一组动作,这些动作是顺序执行的,有时间设计者希望执行某个/些动作后就停止继续执行后面的动作,这时候可以通过stopPropagation来停止执行后面配置的所有动作。
{"type": "page","title": "只执行3个动作中的前两个动作","body": [{"type": "button","label": "弹出2个提示",level: 'primary',"onEvent": {"click": {"actions": [{"actionType": "toast",args: {"msgType": 'info',"msg": '动作1'}},{"actionType": "toast",args: {"msgType": 'info',"msg": '动作2'},"stopPropagation": true},{"actionType": "toast",args: {"msgType": 'info',"msg": '动作3',"position": 'top-right'}}]}}}]}
自定义组件接入事件动作
需求场景主要是想要自定义组件的内部事件暴露出去,能够通过对事件的监听来执行所需动作,并希望自定义组件自身的动作能够被其他组件调用。接入方法是通过props.dispatchEvent派发自身的各种事件,使其具备更灵活的交互设计能力;通过实现doAction方法实现其他组件对其专属动作的调用,需要注意的是,此处依赖内部的 Scoped Context来实现自身的注册,可以参考 组件间通信。
属性表
| 属性名 | 类型 | 默认值 | 说明 | |
|---|---|---|---|---|
| actionType | string |
- | 动作名称 | |
| args | object |
- | 动作参数{key:value},支持数据映射 |
|
| preventDefault | boolean\ |
表达式 | false | 阻止事件默认行为,> 1.10.0 及以上版本支持表达式 |
| stopPropagation | boolean\ |
表达式 | false | 停止后续动作执行,> 1.10.0 及以上版本支持表达式 |
| expression | boolean\ |
表达式 | - | 执行条件,不设置表示默认执行 |
| outputVar | string |
- | 输出数据变量名 |
