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

在构建复杂的应用时,组件间的通信是一个常见的需求。
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%')
  }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值