在构建复杂的应用时,组件间的通信是一个常见的需求。HarmonyOS 提供了多种机制来实现这种通信,包括 emitter、eventHub 以及基于 @Provide、@Consume、@Watch 的响应式数据流。
参考官方文档:
【状态管理最佳实践】
https://developer.huawei.com/consumer/cn/doc/best-practices-V5/bpta-status-management-V5
【EventHub】
https://developer.huawei.com/consumer/cn/doc/harmonyos-references-V5/js-apis-inner-application-eventhub-V5
【emitter】
https://developer.huawei.com/consumer/cn/doc/harmonyos-references-V5/js-apis-emitter-V5#emitteron
以下是我常用的方式总结
方案一:自定义事件调度器
自定义事件调度器是一种简单有效的通信方式,它通过定义静态方法来管理事件的发送和接收。这种方式的好处在于其实现相对直接,不需要依赖外部框架。
示例代码:
class EventDispatcher {
static childCallback?: (value: number) => void;
static dispatchToChild(value: number) {
if (EventDispatcher.childCallback) {
EventDispatcher.childCallback(value);
}
}
}
@Component
struct ChildComponent {
@State value: string = ""
aboutToAppear(): void {
EventDispatcher.childCallback = (value: number) => {
this.handleChildMethod(value);
};
}
handleChildMethod(value: number) {
console.info('我是子组件方法', '父组件传递的值为:' + value);
this.value = String(value)
}
build() {
Column() {
Text(`我是子组件,父组件传递的内容是:${this.value}`)
}.width('100%');
}
}
@Entry
@Component
struct Index {
build() {
Column() {
Button('调用子组件方法').onClick(() => {
EventDispatcher.dispatchToChild(33);
});
ChildComponent();
}
.width('100%');
}
}
复制代码
方案二:使用 emitter
emitter 是一种更为动态的事件管理方式,它可以绑定事件处理函数,并在特定条件下触发这些处理函数。这种方法适用于需要在不同组件间传递复杂数据的情况。
示例代码:
import { emitter } from '@kit.BasicServicesKit';
@Component
struct ChildComponent {
@State value:number = 0
aboutToAppear(): void {
emitter.on({ eventId: 1 }, (event) => {
if (event.data && event.data.data) {
this.handleChildMethod(event.data.data as number);
this.value = event.data.data
}
});
}
handleChildMethod(value: number) {
console.info('我是子组件方法', '父组件传递的值为:' + value);
}
build() {
Column() {
Text(`我是子组件,父组件传递的值为:${this.value}`)
}.width('100%');
}
}
@Entry
@Component
struct Index {
build() {
Column() {
Button('调用子组件方法').onClick(() => {
emitter.emit(
{ eventId: 1, priority: emitter.EventPriority.IMMEDIATE },
{ data: { 'data': 33 } }
);
});
ChildComponent();
}
.width('100%');
}
}
复制代码
方案三:使用 eventHub
eventHub 是另一种事件管理机制,它允许组件间通过事件名来进行通信。相比前两种方法,它可能更接近 Vue.js 的事件总线模式。
示例代码:
@Component
struct ChildComponent {
@State value :number = -1
aboutToAppear(): void {
getContext(this).eventHub.on('1', (data: number) => {
this.handleChildMethod(data as number);
});
}
handleChildMethod(value: number) {
console.info('我是子组件方法', '父组件传递的值为:' + value);
this.value = value
}
build() {
Column() {
Text(`我是子组件,父组件传递的值为:${this.value}`)
}.width('100%');
}
}
@Entry
@Component
struct Index {
build() {
Column() {
Button('调用子组件方法').onClick(() => {
getContext(this).eventHub.emit('1', 33);
});
ChildComponent();
}
.width('100%');
}
}
复制代码
方案四:基于 @Provide、@Consume、@Watch 的数据共享
对于更高级的数据共享需求,HarmonyOS 提供了 @Provide、@Consume 和 @Watch 注解。这些注解可以用来在父子组件间共享状态,并且可以监听状态变化来自动更新 UI。
示例代码:
@Component
struct Page012Child {
@Consume @Watch('onDataChanged') array: Array<Object>
@Consume @Watch('onDataChanged') index: number
build() {
Column() {
Text(`array:${JSON.stringify(this.array)}`)
Text(`index:${this.index}`)
Text(`每次this.index变化时,自定义onDataChanged方法会回调,注意首次不会回调`)
}
}
onDataChanged() {
console.info('====onDataChanged')
}
}
@Entry
@Component
struct Page012 {
@Provide array: Array<Object> = new Array<Object>()
@Provide index: number = 0
build() {
Column() {
Button('测试').onClick(() => {
this.array.push("abc")
this.index++
})
Page012Child()
}
.width('100%')
.height('100%')
}
}
复制代码
评论