diff --git a/docs/zh-CN/components/container.md b/docs/zh-CN/components/container.md index 05bff9331..a2280cad4 100755 --- a/docs/zh-CN/components/container.md +++ b/docs/zh-CN/components/container.md @@ -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}" + } + } + ] + } + } +} +``` diff --git a/packages/amis-editor/src/plugin/Container.tsx b/packages/amis-editor/src/plugin/Container.tsx index 3243416e0..f253b2092 100644 --- a/packages/amis-editor/src/plugin/Container.tsx +++ b/packages/amis-editor/src/plugin/Container.tsx @@ -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) + }) + ] } ]); }; diff --git a/packages/amis/__tests__/event-action/renderers/container.test.tsx b/packages/amis/__tests__/event-action/renderers/container.test.tsx new file mode 100644 index 000000000..13e6bb475 --- /dev/null +++ b/packages/amis/__tests__/event-action/renderers/container.test.tsx @@ -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' + }); + }); +}); diff --git a/packages/amis/src/renderers/Container.tsx b/packages/amis/src/renderers/Container.tsx index f0236f547..d0731712e 100644 --- a/packages/amis/src/renderers/Container.tsx +++ b/packages/amis/src/renderers/Container.tsx @@ -3,6 +3,7 @@ import merge from 'lodash/merge'; import { Renderer, RendererProps, + autobind, buildStyle, isPureVariable, resolveVariableAndFilter @@ -128,6 +129,24 @@ export default class Container extends React.Component< } }; + @autobind + handleClick(e: React.MouseEvent) { + const {dispatchEvent, data} = this.props; + dispatchEvent(e, data); + } + + @autobind + handleMouseEnter(e: React.MouseEvent) { + const {dispatchEvent, data} = this.props; + dispatchEvent(e, data); + } + + @autobind + handleMouseLeave(e: React.MouseEvent) { + const {dispatchEvent, data} = this.props; + dispatchEvent(e, data); + } + renderBody(): JSX.Element | null { const { children, @@ -189,6 +208,9 @@ export default class Container extends React.Component< size && size !== 'none' ? `Container--${size}` : '', className )} + onClick={this.handleClick} + onMouseEnter={this.handleMouseEnter} + onMouseLeave={this.handleMouseLeave} style={buildStyle(style, data)} > {this.renderBody()}