mirror of
https://gitee.com/baidu/amis.git
synced 2024-12-02 11:58:10 +08:00
feat:动作上下文补充$$用于获取组件当前数据域
This commit is contained in:
parent
d9e9204206
commit
09169c26b2
@ -12,26 +12,67 @@ order: 9
|
|||||||
|
|
||||||
上一节我们介绍了如何实现联动,是比较基础和局限的,而事件动作是更简单、更灵活、更高级的用法,可以解决复杂的 UI 交互场景,支持渲染器事件监听和响应设计,无需关心组件层级关系。例如:
|
上一节我们介绍了如何实现联动,是比较基础和局限的,而事件动作是更简单、更灵活、更高级的用法,可以解决复杂的 UI 交互场景,支持渲染器事件监听和响应设计,无需关心组件层级关系。例如:
|
||||||
|
|
||||||
- 传递数据
|
- http 请求:发送 http 请求
|
||||||
- 点击「按钮」,发送一个远程请求,返回的数据回填给一个表单
|
- 弹窗提示:执行弹窗、抽屉打开和 toast 提示
|
||||||
- 弹窗提交后,将弹窗内表单数据回填给另一个表单
|
- 页面跳转:页面链接跳转
|
||||||
- 联动刷新
|
- 浏览器相关:回退、前进、后退、刷新
|
||||||
- 下拉选择不同项,联动刷新表单数据
|
- 刷新组件:联动刷新表单数据,即数据重新加载
|
||||||
- 状态控制
|
- 组件状态:控制指定组件的显示/隐藏、启用/禁用、展示态/编辑态
|
||||||
- 勾选不同按钮,控制相应组件的显示/隐藏
|
- 组件特性动作:执行指定组件的专有动作,例如执行表单的提交动作
|
||||||
- 勾选不同按钮,控制相应组件的启用/禁用
|
- 组件数据:更新指定组件的数据域
|
||||||
- 多个组件监听同一个事件做出不同响应
|
- 广播:多个组件监听同一个事件做出不同响应
|
||||||
- 下拉选择不同项,组件 A 监听后发送一个远程请求,组件 B 监听后进行刷新
|
- JS 脚本:通过编写 JS 代码片段实现所需逻辑,同时支持 JS 代码内执行动作
|
||||||
- 逻辑编排
|
- 逻辑编排:条件、循环、排他、并行
|
||||||
- 针对监听到的事件,循环执行一些动作作为响应,还可以控制循环跳出或跳过
|
|
||||||
- 针对监听到的事件,根据条件选择性的执行动作响应
|
|
||||||
- 针对监听到的事件,并行执行多个动作作为响应
|
|
||||||
- 执行完当前动作后,可以选择是否继续执行后续动作,是否关闭事件默认行为的执行
|
|
||||||
|
|
||||||
## 基本使用
|
## 基本使用
|
||||||
|
|
||||||
|
### onEvent
|
||||||
|
|
||||||
通过`onEvent`属性实现渲染器事件与响应动作的绑定。`onEvent`内配置事件和动作映射关系,`actions`是事件对应的响应动作的集合。
|
通过`onEvent`属性实现渲染器事件与响应动作的绑定。`onEvent`内配置事件和动作映射关系,`actions`是事件对应的响应动作的集合。
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"type": "button",
|
||||||
|
"label": "尝试点击、鼠标移入/移出",
|
||||||
|
"level": "primary",
|
||||||
|
"onEvent": {
|
||||||
|
"click": { // 监听点击事件
|
||||||
|
"actions": [ // 执行的动作列表
|
||||||
|
{
|
||||||
|
"actionType": "toast", // 执行toast提示动作
|
||||||
|
"args": { // 动作参数
|
||||||
|
"msgType": "info",
|
||||||
|
"msg": "派发点击事件"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"mouseenter": {{ // 监听鼠标移入事件
|
||||||
|
"actions": [
|
||||||
|
{
|
||||||
|
"actionType": "toast",
|
||||||
|
"args": {
|
||||||
|
"msgType": "info",
|
||||||
|
"msg": "派发鼠标移入事件"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"mouseleave": {{ // 监听鼠标移出事件
|
||||||
|
"actions": [
|
||||||
|
{
|
||||||
|
"actionType": "toast",
|
||||||
|
"args": {
|
||||||
|
"msgType": "info",
|
||||||
|
"msg": "派发鼠标移出事件"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
```schema
|
```schema
|
||||||
{
|
{
|
||||||
type: 'page',
|
type: 'page',
|
||||||
@ -80,6 +121,94 @@ order: 9
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### 上下文
|
||||||
|
|
||||||
|
执行动作时,可以通过`${event.data}`获取事件对象的数据、通过`${$$}`获取组件当前数据域,例如:
|
||||||
|
|
||||||
|
```schema
|
||||||
|
{
|
||||||
|
"type": "page",
|
||||||
|
data: {
|
||||||
|
p1: 'p1'
|
||||||
|
},
|
||||||
|
"body": {
|
||||||
|
"type": "form",
|
||||||
|
debug: true,
|
||||||
|
"api": {
|
||||||
|
url: "https://3xsw4ap8wah59.cfc-execute.bj.baidubce.com/api/amis-mock/mock2/form/saveForm",
|
||||||
|
method: "post",
|
||||||
|
data: {
|
||||||
|
"&": '$$',
|
||||||
|
job: 'coder'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data: {
|
||||||
|
job: 'hr'
|
||||||
|
},
|
||||||
|
"body": [
|
||||||
|
{
|
||||||
|
type: 'alert',
|
||||||
|
"body": "监听姓名值变化,执行动作时读取输入的内容;监听年龄值变化,执行动作时读取input-text组件当前数据域(表单数据)",
|
||||||
|
"level": "info",
|
||||||
|
"className": "mb-1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "input-text",
|
||||||
|
"name": "name",
|
||||||
|
"label": "姓名:",
|
||||||
|
onEvent: {
|
||||||
|
change: {
|
||||||
|
actions: [
|
||||||
|
{
|
||||||
|
actionType: 'toast',
|
||||||
|
args: {
|
||||||
|
msg: '${name}'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "input-text",
|
||||||
|
"name": "age",
|
||||||
|
"label": "年龄:",
|
||||||
|
onEvent: {
|
||||||
|
change: {
|
||||||
|
actions: [
|
||||||
|
{
|
||||||
|
actionType: 'toast',
|
||||||
|
args: {
|
||||||
|
msg: '${$$|json}'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
onEvent: {
|
||||||
|
submitSucc: {
|
||||||
|
actions: [
|
||||||
|
{
|
||||||
|
actionType: 'toast',
|
||||||
|
args: {
|
||||||
|
msg: '${event.data|json}'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
actionType: 'toast',
|
||||||
|
args: {
|
||||||
|
msg: '${$$|json}'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
### 运行日志
|
### 运行日志
|
||||||
|
|
||||||
可以在浏览器控制台查看运行日志,类似如下
|
可以在浏览器控制台查看运行日志,类似如下
|
||||||
@ -92,9 +221,9 @@ run action ajax
|
|||||||
|
|
||||||
代表运行了 ajax 动作,第二行是传递的参数和数据,第三行是执行完动作之后的 `event` 值,可以用做后续动作的参数。
|
代表运行了 ajax 动作,第二行是传递的参数和数据,第三行是执行完动作之后的 `event` 值,可以用做后续动作的参数。
|
||||||
|
|
||||||
## 事件与动作
|
## 事件与动作分类
|
||||||
|
|
||||||
事件包含`渲染器事件`和`广播事件`,监听这些事件时,可以通过`event.data`来获取事件对象的数据。
|
事件包含`渲染器事件`和`广播事件`。
|
||||||
|
|
||||||
- 渲染器事件,由具体的渲染器组件提供,每个渲染器组件暴露的事件可以查看具体的[组件文档的事件表](../../components/page#事件表);
|
- 渲染器事件,由具体的渲染器组件提供,每个渲染器组件暴露的事件可以查看具体的[组件文档的事件表](../../components/page#事件表);
|
||||||
- 广播事件,即自定义事件,可以自定义派发的事件名称`eventName`,其他渲染器可以监听该自定义事件并配置响应动作。
|
- 广播事件,即自定义事件,可以自定义派发的事件名称`eventName`,其他渲染器可以监听该自定义事件并配置响应动作。
|
||||||
@ -1991,7 +2120,7 @@ registerAction('my-action', new MyAction());
|
|||||||
|
|
||||||
通过配置`actionType: 'for'`实现循环逻辑。
|
通过配置`actionType: 'for'`实现循环逻辑。
|
||||||
|
|
||||||
**单层循环**
|
### 单层循环
|
||||||
|
|
||||||
```schema
|
```schema
|
||||||
{
|
{
|
||||||
@ -2043,7 +2172,7 @@ registerAction('my-action', new MyAction());
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
**嵌套循环**
|
### 嵌套循环
|
||||||
|
|
||||||
```schema
|
```schema
|
||||||
{
|
{
|
||||||
@ -2152,7 +2281,7 @@ registerAction('my-action', new MyAction());
|
|||||||
| -------- | ---------------------------------------------------- | ------ | ------------------------------------- |
|
| -------- | ---------------------------------------------------- | ------ | ------------------------------------- |
|
||||||
| children | Array<[动作](../../docs/concepts/event-action#动作)> | - | 子动作,可以通过`break动作`来跳出循环 |
|
| children | Array<[动作](../../docs/concepts/event-action#动作)> | - | 子动作,可以通过`break动作`来跳出循环 |
|
||||||
|
|
||||||
## Break 动作
|
### Break 动作
|
||||||
|
|
||||||
通过配置`actionType: 'for'`和`actionType: 'break'`实现循环跳出。
|
通过配置`actionType: 'for'`和`actionType: 'break'`实现循环跳出。
|
||||||
|
|
||||||
@ -2219,7 +2348,7 @@ registerAction('my-action', new MyAction());
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## Continue 动作
|
### Continue 动作
|
||||||
|
|
||||||
通过配置`actionType: 'for'`和`actionType: 'continue'`实现循环跳过。
|
通过配置`actionType: 'for'`和`actionType: 'continue'`实现循环跳过。
|
||||||
|
|
||||||
|
@ -181,19 +181,31 @@ export const runAction = async (
|
|||||||
renderer: ListenerContext,
|
renderer: ListenerContext,
|
||||||
event: any
|
event: any
|
||||||
) => {
|
) => {
|
||||||
|
// 追加数据
|
||||||
|
let additional: any = {
|
||||||
|
event
|
||||||
|
};
|
||||||
|
|
||||||
|
// $$默认为renderer.props.data,兼容表单项值变化时的data读取
|
||||||
|
if (!event.data.$$) {
|
||||||
|
additional = {
|
||||||
|
event,
|
||||||
|
$$: renderer.props.data // 部分组件交互后会有更新,如果想要获取那部分数据,可以通过事件数据获取
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
// 用户可能,需要用到事件数据和当前域的数据,因此merge事件数据和当前渲染器数据
|
// 用户可能,需要用到事件数据和当前域的数据,因此merge事件数据和当前渲染器数据
|
||||||
// 需要保持渲染器数据链完整
|
// 需要保持渲染器数据链完整
|
||||||
// 注意:并行ajax请求结果必须通过event取值
|
// 注意:并行ajax请求结果必须通过event取值
|
||||||
const mergeData = createObject(
|
const mergeData = createObject(
|
||||||
createObject(
|
createObject(
|
||||||
renderer.props.data.__super
|
renderer.props.data.__super
|
||||||
? createObject(renderer.props.data.__super, {event})
|
? createObject(renderer.props.data.__super, additional)
|
||||||
: {event},
|
: additional,
|
||||||
renderer.props.data
|
renderer.props.data
|
||||||
),
|
),
|
||||||
event.data
|
event.data
|
||||||
);
|
);
|
||||||
|
|
||||||
// 兼容一下1.9.0之前的版本
|
// 兼容一下1.9.0之前的版本
|
||||||
const expression = actionConfig.expression ?? actionConfig.execOn;
|
const expression = actionConfig.expression ?? actionConfig.execOn;
|
||||||
|
|
||||||
|
@ -258,8 +258,12 @@ export const resolveEventData = (props: any, data: any, valueKey?: string) => {
|
|||||||
props.name && valueKey
|
props.name && valueKey
|
||||||
? {
|
? {
|
||||||
...data,
|
...data,
|
||||||
|
[props.name]: data[valueKey],
|
||||||
|
$$: {
|
||||||
|
...props.data,
|
||||||
[props.name]: data[valueKey]
|
[props.name]: data[valueKey]
|
||||||
}
|
}
|
||||||
|
}
|
||||||
: data
|
: data
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import {Renderer, RendererProps} from 'amis-core';
|
import {createObject, Renderer, RendererProps} from 'amis-core';
|
||||||
import {Overlay} from 'amis-core';
|
import {Overlay} from 'amis-core';
|
||||||
import {PopOver} from 'amis-core';
|
import {PopOver} from 'amis-core';
|
||||||
import {TooltipWrapper} from 'amis-ui';
|
import {TooltipWrapper} from 'amis-ui';
|
||||||
@ -180,9 +180,13 @@ export default class DropDownButton extends React.Component<
|
|||||||
}
|
}
|
||||||
|
|
||||||
async open() {
|
async open() {
|
||||||
await this.props.dispatchEvent('mouseenter', {
|
const {dispatchEvent, data, buttons} = this.props;
|
||||||
items: this.props.buttons // 为了保持名字统一
|
await dispatchEvent(
|
||||||
});
|
'mouseenter',
|
||||||
|
createObject(data, {
|
||||||
|
items: buttons // 为了保持名字统一
|
||||||
|
})
|
||||||
|
);
|
||||||
this.setState({
|
this.setState({
|
||||||
isOpened: true
|
isOpened: true
|
||||||
});
|
});
|
||||||
@ -190,7 +194,10 @@ export default class DropDownButton extends React.Component<
|
|||||||
|
|
||||||
close() {
|
close() {
|
||||||
this.timer = setTimeout(() => {
|
this.timer = setTimeout(() => {
|
||||||
this.props.dispatchEvent('mouseleave', {items: this.props.buttons});
|
this.props.dispatchEvent(
|
||||||
|
'mouseleave',
|
||||||
|
createObject(this.props.data, {items: this.props.buttons})
|
||||||
|
);
|
||||||
this.setState({
|
this.setState({
|
||||||
isOpened: false
|
isOpened: false
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user