在鸿蒙HarmonyOS开发中EventEmitter 是一种用于事件发布/订阅的通信机制常用于组件、Ability、线程或模块之间的解耦通信。它允许一个对象发布者发出事件而其他对象订阅者可以监听并响应这些事件。核心概念与使用场景EventEmitter 的核心是观察者模式的实现。它适用于以下典型场景UIAbility 与 UI 页面之间的通信例如UIAbility 中的业务逻辑处理完成后通过事件通知 UI 页面更新。跨组件通信在复杂的页面中非父子关系的组件可以通过事件进行数据传递。线程间通信Worker 线程或 TaskPool 任务完成后通过事件通知主线程。原生Native/ArkTS与 JavaScript如 React Native之间的通信在混合开发中用于两端的事件传递。主要实现方式在鸿蒙开发中根据不同的使用场景EventEmitter 有几种常见的实现方式1. 使用ohos.events.emitter模块系统基础服务这是鸿蒙系统提供的官方事件发射器功能强大支持跨线程、跨进程的事件通信。它提供了on订阅、emit发送、off取消订阅等核心方法。示例代码ArkTS// 导入基础服务Kit中的Emitter模块 import { emitter } from kit.BasicServicesKit; // 定义事件ID const EVENT_ID: string myEvent; // 订阅事件 emitter.on(EVENT_ID, (eventData: emitter.EventData) { console.log(收到事件数据${JSON.stringify(eventData.data)}); }); // 发送事件可以携带数据 emitter.emit(EVENT_ID, { Hello EventEmitter }); // 取消订阅通常在不需监听时调用例如组件销毁时 // emitter.off(EVENT_ID);特点系统能力需要SystemCapability.Notification.Emitter。跨线程/进程适用于更广泛的通信场景。强类型可以通过泛型GenericEventDataT指定事件数据的类型。2. 使用 UIAbility 的eventHub在 Stage 模型下每个 UIAbility 实例都拥有一个eventHub对象用于该 Ability 内部包括其所属的所有页面的事件通信。它是一种轻量级的线程内事件总线。示例代码结合 UIAbility 和 UI 页面// 在 UIAbility如 EntryAbility.ets中订阅事件 import { UIAbility } from kit.AbilityKit; export default class EntryAbility extends UIAbility { onCreate() { const eventHub this.context.eventHub; eventHub.on(dataLoaded, (string) { console.log(Ability收到数据${data}); }); } } // 在 UI 页面.ets 文件中发送事件 Entry Component struct Index { private context this.getUIContext().getHostContext() as common.UIAbilityContext; build() { Column() { Button(发送事件到Ability) .onClick(() { // 通过 eventHub 发送事件 this.context.eventHub.emit(dataLoaded, 数据来自UI页面); }) } } }特点作用域局限仅限于同一个 UIAbility 内不能跨 Ability 通信。无需导入直接通过 Ability 上下文 (context.eventHub) 访问。轻量高效适合 Ability 内部页面与逻辑的简单通信。3. 自定义 EventEmitter 类你也可以根据需求实现一个简单的 EventEmitter通常用于管理应用内的自定义事件或全局状态变更通知。示例代码自定义类class MyEventEmitter { private events: { [key: string]: Function[] } {}; // 订阅事件 on(event: string, callback: Function): void { if (!this.events[event]) { this.events[event] []; } this.events[event].push(callback); } // 发送事件 emit(event: string, ...args: any[]): void { if (this.events[event]) { this.events[event].forEach(callback { callback(...args); }); } } // 取消订阅 off(event: string, callback?: Function): void { if (!this.events[event]) return; if (!callback) { delete this.events[event]; } else { this.events[event] this.events[event].filter(cb cb ! callback); } } } // 使用示例 const myEmitter new MyEventEmitter(); myEmitter.on(test, (msg: string) { console.log(自定义事件${msg}); }); myEmitter.emit(test, Hello Custom Emitter);特点高度可控可以根据业务需求定制例如添加 once单次监听、错误处理等。应用内全局通常以单例模式导出供多个模块使用。4. 在 React Native 鸿蒙化RNOH开发中在 React Native 应用与鸿蒙原生ArkTS混合开发时EventEmitter 机制也用于两端通信。Native (ArkTS) 给 JS 发消息使用RNInstance的emitDeviceEvent方法。// ArkTS 侧发送事件 this.ctx.rnInstance.emitDeviceEvent(customEvent, { params: { key: value } });JS 侧监听使用DeviceEventEmitter。// React Native JS 侧监听事件 import { DeviceEventEmitter } from react-native; DeviceEventEmitter.addListener(customEvent, (e) { console.log(收到来自Native的事件:, e); });选择建议与注意事项作用域选择同一 UIAbility 内部通信优先使用eventHub。需要跨线程或更通用的场景使用ohos.events.emitter。全局应用状态管理或复杂事件流可考虑自定义 EventEmitter 或结合状态管理工具如 AppStorage。生命周期管理务必在组件或 Ability 销毁时例如aboutToDisappear或onDestroy取消事件订阅防止内存泄漏和无效回调。事件命名建议使用有明确意义的字符串常量作为事件 ID避免拼写错误和冲突。数据传递emit可以携带任意数据但建议保持数据结构的简单和可序列化便于调试和跨线程传递。EventEmitter 是鸿蒙开发中实现松耦合通信的重要工具根据具体场景选择合适的实现方式可以显著提升代码的可维护性和可扩展性。
HarmonyOS ,你所不知道的事件发布/订阅的通信机制-EventEmitter
在鸿蒙HarmonyOS开发中EventEmitter 是一种用于事件发布/订阅的通信机制常用于组件、Ability、线程或模块之间的解耦通信。它允许一个对象发布者发出事件而其他对象订阅者可以监听并响应这些事件。核心概念与使用场景EventEmitter 的核心是观察者模式的实现。它适用于以下典型场景UIAbility 与 UI 页面之间的通信例如UIAbility 中的业务逻辑处理完成后通过事件通知 UI 页面更新。跨组件通信在复杂的页面中非父子关系的组件可以通过事件进行数据传递。线程间通信Worker 线程或 TaskPool 任务完成后通过事件通知主线程。原生Native/ArkTS与 JavaScript如 React Native之间的通信在混合开发中用于两端的事件传递。主要实现方式在鸿蒙开发中根据不同的使用场景EventEmitter 有几种常见的实现方式1. 使用ohos.events.emitter模块系统基础服务这是鸿蒙系统提供的官方事件发射器功能强大支持跨线程、跨进程的事件通信。它提供了on订阅、emit发送、off取消订阅等核心方法。示例代码ArkTS// 导入基础服务Kit中的Emitter模块 import { emitter } from kit.BasicServicesKit; // 定义事件ID const EVENT_ID: string myEvent; // 订阅事件 emitter.on(EVENT_ID, (eventData: emitter.EventData) { console.log(收到事件数据${JSON.stringify(eventData.data)}); }); // 发送事件可以携带数据 emitter.emit(EVENT_ID, { Hello EventEmitter }); // 取消订阅通常在不需监听时调用例如组件销毁时 // emitter.off(EVENT_ID);特点系统能力需要SystemCapability.Notification.Emitter。跨线程/进程适用于更广泛的通信场景。强类型可以通过泛型GenericEventDataT指定事件数据的类型。2. 使用 UIAbility 的eventHub在 Stage 模型下每个 UIAbility 实例都拥有一个eventHub对象用于该 Ability 内部包括其所属的所有页面的事件通信。它是一种轻量级的线程内事件总线。示例代码结合 UIAbility 和 UI 页面// 在 UIAbility如 EntryAbility.ets中订阅事件 import { UIAbility } from kit.AbilityKit; export default class EntryAbility extends UIAbility { onCreate() { const eventHub this.context.eventHub; eventHub.on(dataLoaded, (string) { console.log(Ability收到数据${data}); }); } } // 在 UI 页面.ets 文件中发送事件 Entry Component struct Index { private context this.getUIContext().getHostContext() as common.UIAbilityContext; build() { Column() { Button(发送事件到Ability) .onClick(() { // 通过 eventHub 发送事件 this.context.eventHub.emit(dataLoaded, 数据来自UI页面); }) } } }特点作用域局限仅限于同一个 UIAbility 内不能跨 Ability 通信。无需导入直接通过 Ability 上下文 (context.eventHub) 访问。轻量高效适合 Ability 内部页面与逻辑的简单通信。3. 自定义 EventEmitter 类你也可以根据需求实现一个简单的 EventEmitter通常用于管理应用内的自定义事件或全局状态变更通知。示例代码自定义类class MyEventEmitter { private events: { [key: string]: Function[] } {}; // 订阅事件 on(event: string, callback: Function): void { if (!this.events[event]) { this.events[event] []; } this.events[event].push(callback); } // 发送事件 emit(event: string, ...args: any[]): void { if (this.events[event]) { this.events[event].forEach(callback { callback(...args); }); } } // 取消订阅 off(event: string, callback?: Function): void { if (!this.events[event]) return; if (!callback) { delete this.events[event]; } else { this.events[event] this.events[event].filter(cb cb ! callback); } } } // 使用示例 const myEmitter new MyEventEmitter(); myEmitter.on(test, (msg: string) { console.log(自定义事件${msg}); }); myEmitter.emit(test, Hello Custom Emitter);特点高度可控可以根据业务需求定制例如添加 once单次监听、错误处理等。应用内全局通常以单例模式导出供多个模块使用。4. 在 React Native 鸿蒙化RNOH开发中在 React Native 应用与鸿蒙原生ArkTS混合开发时EventEmitter 机制也用于两端通信。Native (ArkTS) 给 JS 发消息使用RNInstance的emitDeviceEvent方法。// ArkTS 侧发送事件 this.ctx.rnInstance.emitDeviceEvent(customEvent, { params: { key: value } });JS 侧监听使用DeviceEventEmitter。// React Native JS 侧监听事件 import { DeviceEventEmitter } from react-native; DeviceEventEmitter.addListener(customEvent, (e) { console.log(收到来自Native的事件:, e); });选择建议与注意事项作用域选择同一 UIAbility 内部通信优先使用eventHub。需要跨线程或更通用的场景使用ohos.events.emitter。全局应用状态管理或复杂事件流可考虑自定义 EventEmitter 或结合状态管理工具如 AppStorage。生命周期管理务必在组件或 Ability 销毁时例如aboutToDisappear或onDestroy取消事件订阅防止内存泄漏和无效回调。事件命名建议使用有明确意义的字符串常量作为事件 ID避免拼写错误和冲突。数据传递emit可以携带任意数据但建议保持数据结构的简单和可序列化便于调试和跨线程传递。EventEmitter 是鸿蒙开发中实现松耦合通信的重要工具根据具体场景选择合适的实现方式可以显著提升代码的可维护性和可扩展性。