mirror of
https://gitee.com/baidu/amis.git
synced 2024-12-02 03:58:07 +08:00
Merge pull request #7855 from hsm-lv/chore-eventaction
chore:动作执行支持ignoreError,用于忽略执行错误继续执行动作列表
This commit is contained in:
commit
8c93fe7631
@ -3194,7 +3194,7 @@ http 请求动作执行结束后,后面的动作可以通过 `${responseResult
|
|||||||
| id | 组件 ID,即组件的 id 属性的值 |
|
| id | 组件 ID,即组件的 id 属性的值 |
|
||||||
| path | 数据路径,即数据变量的路径 |
|
| path | 数据路径,即数据变量的路径 |
|
||||||
|
|
||||||
# 事件动作干预
|
# 干预动作执行
|
||||||
|
|
||||||
事件动作干预是指执行完当前动作后,干预所监听事件默认处理逻辑和后续其他动作的执行。通过`preventDefault`、`stopPropagation`分别阻止监听事件默认行为和停止下一个动作执行。
|
事件动作干预是指执行完当前动作后,干预所监听事件默认处理逻辑和后续其他动作的执行。通过`preventDefault`、`stopPropagation`分别阻止监听事件默认行为和停止下一个动作执行。
|
||||||
|
|
||||||
@ -3305,6 +3305,65 @@ http 请求动作执行结束后,后面的动作可以通过 `${responseResult
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## 忽略动作报错继续执行
|
||||||
|
|
||||||
|
> `3.3.1` 及以上版本
|
||||||
|
|
||||||
|
默认情况下,尝试执行一个不存在的目标组件动作、JS 脚本执行错误等程序错误都会导致动作执行终止,可以通过`ignoreError: true`来忽略动作报错继续执行后面的动作。
|
||||||
|
|
||||||
|
```schema
|
||||||
|
{
|
||||||
|
"type": "page",
|
||||||
|
"title": "第一个按钮发生错误直接阻塞执行,第二个按钮发生错误后仍然执行",
|
||||||
|
"body": [
|
||||||
|
{
|
||||||
|
type: 'button',
|
||||||
|
label: '无法弹出提示',
|
||||||
|
level: 'primary',
|
||||||
|
className: 'mr-2',
|
||||||
|
onEvent: {
|
||||||
|
click: {
|
||||||
|
actions: [
|
||||||
|
{
|
||||||
|
actionType: 'reload',
|
||||||
|
componentId: 'notfound'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
actionType: 'toast',
|
||||||
|
args: {
|
||||||
|
msg: 'okk'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'button',
|
||||||
|
label: '可以弹出提示',
|
||||||
|
level: 'primary',
|
||||||
|
onEvent: {
|
||||||
|
click: {
|
||||||
|
actions: [
|
||||||
|
{
|
||||||
|
actionType: 'reload',
|
||||||
|
componentId: 'notfound',
|
||||||
|
ignoreError: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
actionType: 'toast',
|
||||||
|
args: {
|
||||||
|
msg: 'okk'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
# 自定义组件接入事件动作
|
# 自定义组件接入事件动作
|
||||||
|
|
||||||
需求场景主要是想要自定义组件的内部事件暴露出去,能够通过对事件的监听来执行所需动作,并希望自定义组件自身的动作能够被其他组件调用。接入方法是通过`props.dispatchEvent`派发自身的各种事件,使其具备更灵活的交互设计能力;通过实现`doAction`方法实现其他组件对其专属动作的调用,需要注意的是,此处依赖内部的 `Scoped Context`来实现自身的注册,可以参考 [组件间通信](../../docs/extend/custom-react#组件间通信)。
|
需求场景主要是想要自定义组件的内部事件暴露出去,能够通过对事件的监听来执行所需动作,并希望自定义组件自身的动作能够被其他组件调用。接入方法是通过`props.dispatchEvent`派发自身的各种事件,使其具备更灵活的交互设计能力;通过实现`doAction`方法实现其他组件对其专属动作的调用,需要注意的是,此处依赖内部的 `Scoped Context`来实现自身的注册,可以参考 [组件间通信](../../docs/extend/custom-react#组件间通信)。
|
||||||
@ -3321,3 +3380,4 @@ http 请求动作执行结束后,后面的动作可以通过 `${responseResult
|
|||||||
| stopPropagation | `boolean`\|[表达式](../concepts/expression)\|[ConditionBuilder](../../components/form/condition-builder) | false | 停止后续动作执行,`> 1.10.0 及以上版本支持表达式,> 2.9.0 及以上版本支持ConditionBuilder` |
|
| stopPropagation | `boolean`\|[表达式](../concepts/expression)\|[ConditionBuilder](../../components/form/condition-builder) | false | 停止后续动作执行,`> 1.10.0 及以上版本支持表达式,> 2.9.0 及以上版本支持ConditionBuilder` |
|
||||||
| expression | `boolean`\|[表达式](../concepts/expression)\|[ConditionBuilder](../../components/form/condition-builder) | - | 执行条件,不设置表示默认执行,`> 1.10.0 及以上版本支持表达式,> 2.9.0 及以上版本支持ConditionBuilder` |
|
| expression | `boolean`\|[表达式](../concepts/expression)\|[ConditionBuilder](../../components/form/condition-builder) | - | 执行条件,不设置表示默认执行,`> 1.10.0 及以上版本支持表达式,> 2.9.0 及以上版本支持ConditionBuilder` |
|
||||||
| outputVar | `string` | - | 输出数据变量名 |
|
| outputVar | `string` | - | 输出数据变量名 |
|
||||||
|
| ignoreError | `boolean` | false | 当动作执行出错后,是否忽略错误继续执行。`3.3.1 及以上版本支持` |
|
||||||
|
@ -24,6 +24,7 @@ export interface ListenerAction {
|
|||||||
description?: string; // 事件描述,actionType: broadcast
|
description?: string; // 事件描述,actionType: broadcast
|
||||||
componentId?: string; // 组件ID,用于直接执行指定组件的动作,指定多个组件时使用英文逗号分隔
|
componentId?: string; // 组件ID,用于直接执行指定组件的动作,指定多个组件时使用英文逗号分隔
|
||||||
componentName?: string; // 组件Name,用于直接执行指定组件的动作,指定多个组件时使用英文逗号分隔
|
componentName?: string; // 组件Name,用于直接执行指定组件的动作,指定多个组件时使用英文逗号分隔
|
||||||
|
ignoreError?: boolean; // 当执行动作发生错误时,是否忽略并继续执行
|
||||||
args?: Record<string, any>; // 动作配置,可以配置数据映射。注意:存在schema配置的动作都不能放在args里面,避免数据域不同导致的解析错误问题
|
args?: Record<string, any>; // 动作配置,可以配置数据映射。注意:存在schema配置的动作都不能放在args里面,避免数据域不同导致的解析错误问题
|
||||||
data?: Record<string, any> | null; // 动作数据参数,可以配置数据映射
|
data?: Record<string, any> | null; // 动作数据参数,可以配置数据映射
|
||||||
dataMergeMode?: 'merge' | 'override'; // 参数模式,合并或者覆盖
|
dataMergeMode?: 'merge' | 'override'; // 参数模式,合并或者覆盖
|
||||||
@ -181,8 +182,19 @@ export const runActions = async (
|
|||||||
actionInstrance = getActionByType('component');
|
actionInstrance = getActionByType('component');
|
||||||
}
|
}
|
||||||
|
|
||||||
// 这些节点的子节点运行逻辑由节点内部实现
|
try {
|
||||||
await runAction(actionInstrance, actionConfig, renderer, event);
|
// 这些节点的子节点运行逻辑由节点内部实现
|
||||||
|
await runAction(actionInstrance, actionConfig, renderer, event);
|
||||||
|
} catch (e) {
|
||||||
|
const ignore = actionConfig.ignoreError ?? false;
|
||||||
|
if (!ignore) {
|
||||||
|
throw Error(
|
||||||
|
`${actionConfig.actionType} 动作执行失败,原因:${
|
||||||
|
e.message || '未知'
|
||||||
|
}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (event.stoped) {
|
if (event.stoped) {
|
||||||
break;
|
break;
|
||||||
|
@ -43,7 +43,9 @@ export class CmptAction implements RendererAction {
|
|||||||
: null;
|
: null;
|
||||||
|
|
||||||
if (key && !component) {
|
if (key && !component) {
|
||||||
throw Error('目标组件没有找到,请检查componentId或componentName是否正确');
|
throw Error(
|
||||||
|
'尝试执行一个不存在的目标组件动作,请检查目标组件非隐藏状态,且正确指定了componentId或componentName'
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (action.actionType === 'setValue') {
|
if (action.actionType === 'setValue') {
|
||||||
|
@ -97,3 +97,70 @@ test('EventAction:prevent', async () => {
|
|||||||
expect(container).toMatchSnapshot();
|
expect(container).toMatchSnapshot();
|
||||||
expect(fetcher).not.toHaveBeenCalled();
|
expect(fetcher).not.toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('EventAction:ignoreError', async () => {
|
||||||
|
const notify = jest.fn();
|
||||||
|
const fetcher = jest.fn().mockImplementation(() =>
|
||||||
|
Promise.resolve({
|
||||||
|
data: {
|
||||||
|
status: 0,
|
||||||
|
msg: 'ok',
|
||||||
|
data: {
|
||||||
|
age: 18
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
);
|
||||||
|
const {getByText, container}: any = render(
|
||||||
|
amisRender(
|
||||||
|
{
|
||||||
|
type: 'page',
|
||||||
|
body: [
|
||||||
|
{
|
||||||
|
type: 'button',
|
||||||
|
label: '按钮',
|
||||||
|
level: 'primary',
|
||||||
|
onEvent: {
|
||||||
|
click: {
|
||||||
|
actions: [
|
||||||
|
{
|
||||||
|
actionType: 'reload',
|
||||||
|
componentId: 'notfound',
|
||||||
|
ignoreError: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
actionType: 'ajax',
|
||||||
|
api: '/api/test3'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
actionType: 'custom',
|
||||||
|
script:
|
||||||
|
"const myMsg = '我是自定义JS';\nsdfsdfsdf();\ndoAction({\n actionType: 'toast',\n args: {\n msg: myMsg\n }\n});\n",
|
||||||
|
ignoreError: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
actionType: 'ajax',
|
||||||
|
api: '/api/test4'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{},
|
||||||
|
makeEnv({
|
||||||
|
getModalContainer: () => container,
|
||||||
|
notify,
|
||||||
|
fetcher
|
||||||
|
})
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
fireEvent.click(getByText('按钮'));
|
||||||
|
await waitFor(() => {
|
||||||
|
expect(fetcher).toHaveBeenCalledTimes(2);
|
||||||
|
expect(fetcher.mock.calls[0][0].url).toEqual('/api/test3');
|
||||||
|
expect(fetcher.mock.calls[1][0].url).toEqual('/api/test4');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import type {IColumn, ITableStore} from 'amis-core/lib/store/table';
|
import type {IColumn, ITableStore} from 'amis-core';
|
||||||
import {observer} from 'mobx-react';
|
import {observer} from 'mobx-react';
|
||||||
|
|
||||||
export function ColGroup({
|
export function ColGroup({
|
||||||
|
Loading…
Reference in New Issue
Block a user