鸿蒙应用示例:跨组件通信实践父组件调用子组件方法及状态共享

在构建复杂的应用时,组件间的通信是一个常见的需求。
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

以下是我常用的方式总结

方案一:自定义事件调度器

自定义事件调度器是一种简单有效的通信方式,它通过定义静态方法来管理事件的发送和接收。这种方式的好处在于其实现相对直接,不需要依赖外部框架。

示例代码:

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
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是一种更为动态的事件管理方式,它可以绑定事件处理函数,并在特定条件下触发这些处理函数。这种方法适用于需要在不同组件间传递复杂数据的情况。

示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
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的事件总线模式。

示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
@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。

示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
@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%')
  }
}

  

posted @   zhongcx  阅读(647)  评论(0编辑  收藏  举报
编辑推荐:
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
点击右上角即可分享
微信分享提示