Merge pull request #7516 from igrowp/container-click

feat: 容器组件支持鼠标点击、移入、移出事件
This commit is contained in:
wutong 2023-07-19 14:56:03 +08:00 committed by GitHub
commit 193c01500c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 272 additions and 2 deletions

View File

@ -17,7 +17,7 @@ Container 是一种容器组件,它可以渲染其他 amis 组件。
```schema: scope="body"
{
"type": "container",
"body":"这里是容器内容区"
"body": "这里是容器内容区"
}
```
@ -57,3 +57,87 @@ container 可以通过 style 来设置样式,比如背景色或背景图,注
| wrapperComponent | `string` | `"div"` | 容器标签名 |
| style | `Object` | | 自定义样式 |
| body | [SchemaNode](../../docs/types/schemanode) | | 容器内容 |
## 事件表
> 3.3.0 及以上版本
当前组件会对外派发以下事件,可以通过`onEvent`来监听这些事件,并通过`actions`来配置执行的动作,在`actions`中可以通过`${事件参数名}`或`${event.data.[事件参数名]}`来获取事件产生的数据,详细查看[事件动作](../../docs/concepts/event-action)。
| 事件名称 | 事件参数 | 说明 |
| ---------- | -------- | -------------- |
| click | - | 点击时触发 |
| mouseenter | - | 鼠标移入时触发 |
| mouseleave | - | 鼠标移出时触发 |
### click
鼠标点击。可以尝试通过`${event.context.nativeEvent}`获取鼠标事件对象。
```schema: scope="body"
{
"type": "container",
"body": "这里是容器内容区",
"onEvent": {
"click": {
"actions": [
{
"actionType": "toast",
"args": {
"msgType": "info",
"msg": "${event.context.nativeEvent.type}"
}
}
]
}
}
}
```
### mouseenter
鼠标移入。可以尝试通过`${event.context.nativeEvent}`获取鼠标事件对象。
```schema: scope="body"
{
"type": "container",
"body": "这里是容器内容区",
"onEvent": {
"mouseenter": {
"actions": [
{
"actionType": "toast",
"args": {
"msgType": "info",
"msg": "${event.context.nativeEvent.type}"
}
}
]
}
}
}
```
### mouseleave
鼠标移出。可以尝试通过`${event.context.nativeEvent}`获取鼠标事件对象。
```schema: scope="body"
{
"type": "container",
"body": "这里是容器内容区",
"onEvent": {
"mouseleave": {
"actions": [
{
"actionType": "toast",
"args": {
"msgType": "info",
"msg": "${event.context.nativeEvent.type}"
}
}
]
}
}
}
```

View File

@ -7,8 +7,10 @@ import {
ResizeMoveEventContext,
registerEditorPlugin,
defaultValue,
getSchemaTpl
getSchemaTpl,
RendererPluginEvent
} from 'amis-editor-core';
import {getEventControlConfig} from '../renderer/event-control';
export class ContainerPlugin extends LayoutBasePlugin {
static id = 'ContainerPlugin';
@ -49,6 +51,76 @@ export class ContainerPlugin extends LayoutBasePlugin {
panelJustify = true;
// 事件定义
events: RendererPluginEvent[] = [
{
eventName: 'click',
eventLabel: '点击',
description: '点击时触发',
dataSchema: [
{
type: 'object',
properties: {
context: {
type: 'object',
title: '上下文',
properties: {
nativeEvent: {
type: 'object',
title: '鼠标事件对象'
}
}
}
}
}
]
},
{
eventName: 'mouseenter',
eventLabel: '鼠标移入',
description: '鼠标移入时触发',
dataSchema: [
{
type: 'object',
properties: {
context: {
type: 'object',
title: '上下文',
properties: {
nativeEvent: {
type: 'object',
title: '鼠标事件对象'
}
}
}
}
}
]
},
{
eventName: 'mouseleave',
eventLabel: '鼠标移出',
description: '鼠标移出时触发',
dataSchema: [
{
type: 'object',
properties: {
context: {
type: 'object',
title: '上下文',
properties: {
nativeEvent: {
type: 'object',
title: '鼠标事件对象'
}
}
}
}
}
]
}
];
panelBodyCreator = (context: BaseEventContext) => {
const curRendererSchema = context?.schema;
const isRowContent =
@ -238,6 +310,16 @@ export class ContainerPlugin extends LayoutBasePlugin {
body: getSchemaTpl('collapseGroup', [
...getSchemaTpl('theme:common', {exclude: ['layout']})
])
},
{
title: '事件',
className: 'p-none',
body: [
getSchemaTpl('eventControl', {
name: 'onEvent',
...getEventControlConfig(this.manager, context)
})
]
}
]);
};

View File

@ -0,0 +1,82 @@
import {fireEvent, render, waitFor} from '@testing-library/react';
import '../../../src';
import {render as amisRender} from '../../../src';
import {makeEnv} from '../../helper';
test('EventAction:container', async () => {
const notify = jest.fn();
const {getByText, container}: any = render(
amisRender(
{
type: 'page',
body: [
{
type: 'container',
body: '这里是容器内容区',
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: '派发鼠标移出事件'
}
}
]
}
}
}
]
},
{},
makeEnv({
notify
})
)
);
fireEvent.click(getByText('这里是容器内容区'));
await waitFor(() => {
expect(notify).toHaveBeenCalledWith('info', '派发点击事件', {
msg: '派发点击事件',
msgType: 'info'
});
});
fireEvent.mouseEnter(getByText('这里是容器内容区'));
await waitFor(() => {
expect(notify).toHaveBeenCalledWith('info', '派发鼠标移入事件', {
msg: '派发鼠标移入事件',
msgType: 'info'
});
});
fireEvent.mouseLeave(getByText('这里是容器内容区'));
await waitFor(() => {
expect(notify).toHaveBeenCalledWith('info', '派发鼠标移出事件', {
msg: '派发鼠标移出事件',
msgType: 'info'
});
});
});

View File

@ -3,6 +3,7 @@ import merge from 'lodash/merge';
import {
Renderer,
RendererProps,
autobind,
buildStyle,
isPureVariable,
resolveVariableAndFilter
@ -128,6 +129,24 @@ export default class Container<T> extends React.Component<
}
};
@autobind
handleClick(e: React.MouseEvent<any>) {
const {dispatchEvent, data} = this.props;
dispatchEvent(e, data);
}
@autobind
handleMouseEnter(e: React.MouseEvent<any>) {
const {dispatchEvent, data} = this.props;
dispatchEvent(e, data);
}
@autobind
handleMouseLeave(e: React.MouseEvent<any>) {
const {dispatchEvent, data} = this.props;
dispatchEvent(e, data);
}
renderBody(): JSX.Element | null {
const {
children,
@ -189,6 +208,9 @@ export default class Container<T> extends React.Component<
size && size !== 'none' ? `Container--${size}` : '',
className
)}
onClick={this.handleClick}
onMouseEnter={this.handleMouseEnter}
onMouseLeave={this.handleMouseLeave}
style={buildStyle(style, data)}
>
{this.renderBody()}