Skip to content

事件动作机制

在 Neo 平台中,自定义组件之间的数据联动和交互响应可通过 事件动作机制 完成:一方组件 触发事件,另一方通过 组件动作(组件函数) 响应。

下文说明如何声明可触发事件、可执行动作,以及可选的广播方式(不推荐作为主方案)。

一、添加可触发的组件事件

1. 在组件代码中声明可触发事件

步骤 1:导入 NeoEvent

说明: 无需在项目中安装 neo-ui-common;组件在 Neo 平台运行时会由平台注入该模块。

typescript
// @ts-ignore
import { NeoEvent } from 'neo-ui-common';

步骤 2:用 @NeoEvent.dispatch 标记可对外触发的方法

typescript
/**
 * 表单提交事件
 */
@NeoEvent.dispatch
onSubmit() {
  console.log('触发了表单提交事件:', this.props);
}

2. 在组件模型中定义可触发的组件事件

在组件代码中声明可触发事件后,页面设计器仍不知道该组件会触发哪些事件,需要在 组件模型 中声明,供属性配置面板中做事件绑定:

typescript
/**
 * @file Object Form 表单组件对接编辑器的描述文件
 * @description 定义组件在 Neo 平台编辑器中的配置信息
 */
export class EntityFormModel {
  // ... 组件模型其他内容

  /**
   * 声明当前组件会触发的所有事件(设计器用于事件动作配置)
   */
  events = [
    {
      apiKey: 'onSubmit',
      label: '提交表单后',
      helpText: '表单提交后触发该事件',
    },
  ];
}

3. 发布后在设计器中验证

发布自定义组件后,在页面设计器画布区选中该自定义组件,即可在右侧属性配置面板中看到上述添加的组件事件,在此处可与其他组件的动作进行绑定。

二、添加可执行的组件动作(组件函数)

1. 在组件代码中实现可执行的组件动作

步骤 1:导入 NeoEvent

说明: 无需单独安装 neo-ui-common,运行时会自动注入。

typescript
// @ts-ignore
import { NeoEvent } from 'neo-ui-common';

步骤 2:用 @NeoEvent.function 标记供事件调用的方法

typescript
/**
 * 刷新表格数据
 * @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. 在组件模型中定义可执行的组件动作(组件函数)

同样需要在组件模型中声明,页面设计器才知道有哪些 组件动作 可被绑定:

typescript
/**
 * @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)。

typescript
// @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

typescript
// @ts-ignore
import { NeoEvent } from 'neo-ui-common';

步骤 2:在适当时机调用 NeoEvent.broadcast

typescript
componentDidMount() {
  // ... 其他逻辑

  console.log('触发广播事件 EntityFormInit。');
  NeoEvent.broadcast('entityFormInit', this.props);
}

2. 监听广播

步骤 1:导入 NeoEvent

typescript
// @ts-ignore
import { NeoEvent } from 'neo-ui-common';

步骤 2:在 componentDidMount 等生命周期中注册监听

typescript
componentDidMount() {
  // ... 其他逻辑

  NeoEvent.listen('entityFormInit', (eventData: any) => {
    console.log('EntityCardList 收到广播 entityFormInit: ', eventData);
    // ... 其他处理
  });
}