事件动作机制
在 Neo 平台中,自定义组件之间的数据联动和交互响应可通过 事件动作机制 完成:一方组件 触发事件,另一方通过 组件动作(组件函数) 响应。
下文说明如何声明可触发事件、可执行动作,以及可选的广播方式(不推荐作为主方案)。
一、添加可触发的组件事件
1. 在组件代码中声明可触发事件
步骤 1:导入 NeoEvent
说明: 无需在项目中安装
neo-ui-common;组件在 Neo 平台运行时会由平台注入该模块。
// @ts-ignore
import { NeoEvent } from 'neo-ui-common';步骤 2:用 @NeoEvent.dispatch 标记可对外触发的方法
/**
* 表单提交事件
*/
@NeoEvent.dispatch
onSubmit() {
console.log('触发了表单提交事件:', this.props);
}2. 在组件模型中定义可触发的组件事件
在组件代码中声明可触发事件后,页面设计器仍不知道该组件会触发哪些事件,需要在 组件模型 中声明,供属性配置面板中做事件绑定:
/**
* @file Object Form 表单组件对接编辑器的描述文件
* @description 定义组件在 Neo 平台编辑器中的配置信息
*/
export class EntityFormModel {
// ... 组件模型其他内容
/**
* 声明当前组件会触发的所有事件(设计器用于事件动作配置)
*/
events = [
{
apiKey: 'onSubmit',
label: '提交表单后',
helpText: '表单提交后触发该事件',
},
];
}3. 发布后在设计器中验证
发布自定义组件后,在页面设计器画布区选中该自定义组件,即可在右侧属性配置面板中看到上述添加的组件事件,在此处可与其他组件的动作进行绑定。
二、添加可执行的组件动作(组件函数)
1. 在组件代码中实现可执行的组件动作
步骤 1:导入 NeoEvent
说明: 无需单独安装
neo-ui-common,运行时会自动注入。
// @ts-ignore
import { NeoEvent } from 'neo-ui-common';步骤 2:用 @NeoEvent.function 标记供事件调用的方法
/**
* 刷新表格数据
* @param page 页码,默认为 1
* @param pageSize 每页条数,默认为 10
*/
@NeoEvent.function
async refreshListData(page = 1, pageSize = 10) {
const { xObjectApiKey, autoFetchData } = this.props.xObjectDataApi || {};
if (!xObjectApiKey) return;
this.setState({ loading: true, error: null });
try {
const result = await xObject.query(this.props.xObjectDataApi);
if (result && result.status) {
const records = result.data || [];
const totalSize = result.totalSize || 0;
this.setState({
dataSource: records,
pagination: {
current: page,
pageSize,
total: totalSize,
},
loading: false,
});
} else {
this.setState({
error: result?.msg || '获取数据失败',
loading: false,
});
}
} catch (error: any) {
this.setState({
error: error.message || '获取数据失败',
loading: false,
});
}
}2. 在组件模型中定义可执行的组件动作(组件函数)
同样需要在组件模型中声明,页面设计器才知道有哪些 组件动作 可被绑定:
/**
* @file XObject 表格组件对接编辑器的描述文件
* @description 定义组件在 Neo 平台编辑器中的配置信息
*/
export class EntityFormModel {
// ... 组件模型其他内容
// 当前组件支持的函数列表(其他组件可通过事件动作调用)
functions = [
{
apiKey: 'refreshListData',
label: '刷新表格数据',
helpTextKey: '刷新当前表格数据',
}
];
}3. 自定义组件需继承 BaseCmp
自定义组件继承 BaseCmp 后,在 Neo 平台运行时其他自定义组件可通过组件ID获取该自定义组件的实例,执行该自定义组件的组件函数(组件动作)。
若组件函数内使用 this,请在构造函数中对组件函数进行上下文绑定,例如:this.refreshData = this.refreshData.bind(this),确保执行事件动作时可以正常获取到组件上下文(this)。
// @ts-ignore
import { BaseCmp, NeoEvent } from 'neo-ui-common';
// 省略其他代码
class TargetNumber extends BaseCmp<TargetNumberProps, TargetNumberState> {
constructor(props: TargetNumberProps) {
super(props);
// 初始化组件状态
this.state = {
recordData: {},
targetNumbers: [],
loading: false,
error: null,
};
this.loadData = this.loadData.bind(this);
}
// 省略组件其他代码
@NeoEvent.function
async loadData() {
...组件函数实现
}
render() {
return (
<div
className={`targetNumber__c ${className || ''}`}
style={baseStyleObj}
>
...自定义组件内容
</div>
);
}
}4. 发布后在设计器中验证
发布后,在页面设计器 / 属性配置面板 / 事件配置面板中应能看到上述组件函数,并作为动作目标进行配置。
三、广播事件(可选,不推荐作为主方案)
跨组件广播可用于简单场景,但耦合与调试成本较高,建议优先使用事件动作机制。
1. 触发广播
步骤 1:导入 NeoEvent
// @ts-ignore
import { NeoEvent } from 'neo-ui-common';步骤 2:在适当时机调用 NeoEvent.broadcast
componentDidMount() {
// ... 其他逻辑
console.log('触发广播事件 EntityFormInit。');
NeoEvent.broadcast('entityFormInit', this.props);
}2. 监听广播
步骤 1:导入 NeoEvent
// @ts-ignore
import { NeoEvent } from 'neo-ui-common';步骤 2:在 componentDidMount 等生命周期中注册监听
componentDidMount() {
// ... 其他逻辑
NeoEvent.listen('entityFormInit', (eventData: any) => {
console.log('EntityCardList 收到广播 entityFormInit: ', eventData);
// ... 其他处理
});
}