HarmonyOS Next 状态管理:Event 装饰器实践

目录

一. @Event 修饰器概述

在日常开发中,父子组件之间的数据同步是一个常见需求。虽然可以通过 @Param 结合回调函数实现父子组件的同步刷新,但这种方式较为繁琐。为此,@Event 修饰器应运而生,专门用于简化事件传递和数据同步。

二、@Event 修饰器的限制

使用范围:

- @Event 只能在 ComponentV2 中使用。
修饰范围

- @Event只能修饰回调方法,不能与其他变量搭配使用。相比之下,@Param 既可以修饰回调方法,也可以修饰变量。

三、实践探索

3.1 @Event的简单使用

@Entry
@ComponentV2
struct Index {
  @Local msg: string = "x"

  build() {
    Column({space: 20}) {
      Text(this.msg)
      Button('change value')
        .onClick(() => {
          this.msg += `abc`
        })
      Line().width('100%').height(1).backgroundColor(Color.Gray)
      ChildComponent({cMsg: this.msg, changeValueCallback: () => {
        this.msg += `${Math.round(Math.random() * 100)}`
      }, changeMsgCallback: (msg: string) => {
        this.msg = msg
      }})
    }
  }
}

@ComponentV2
struct ChildComponent {
  @Param cMsg: string = ""
  @Event changeValueCallback: () => void
  @Event changeMsgCallback: (msg: string) => void

  build() {
    Column({space: 12}) {
      Text(this.cMsg)
      Button('调用changeValueCallback')
        .onClick(() => {
          this.changeValueCallback()
        })
      Button('调用changeMsgCallbackk')
        .onClick(() => {
          this.changeMsgCallback(`${Date().toString()}`)
        })
    }
  }
}

关键点

  • 回调方法的使用:子组件无法直接修改 cMsg 的值,但可以通过 @Event 修饰的回调方法间接修改父组件的状态。
  • 事件传递@Event 提供了一种简洁的方式,用于在父子组件之间传递事件并同步数据。
3.2 @Event 装饰可选方法

@Event同样可以装饰可选方法,例子如下:

@Entry
@ComponentV2
struct Index {
  @Local name: string = "name"

  build() {
    Column({space: 20}) {
      Text(this.name)
      Line().width('100%').height(1).backgroundColor(Color.Gray)
      ChildComponent({cName: this.name, changeNameCallback: (name: string) => {
        this.name = name
      }})
    }
  }
}

@ComponentV2
struct ChildComponent {
  @Param cName: string = "cName"
  @Event changeNameCallback?: (name: string) => void

  build() {
    Column({space: 12}) {
      Text(`cName:${this.cName}`)
        .onClick(() => {
          this.changeNameCallback!(`${Date().toString()}`)
        })
    }
  }
}

关键点

  • 可选回调@Event 可以修饰可选回调方法,增强了代码的灵活性。
  • 空值处理:在调用可选回调方法时,需确保其存在(如使用 ! 强制解包)。
3.3 @Event 更新父子组件时机
@Entry
@ComponentV2
struct Index {
  @Local name: string = "name"

  build() {
    Column({space: 20}) {
      Text(this.name)
      Line().width('100%').height(1).backgroundColor(Color.Gray)
      ChildComponent({cName: this.name, changeNameCallback: (name: string) => {
        this.name = name
        console.log(`callback called in father component:${this.name}`)
      }})
    }
  }
}

@ComponentV2
struct ChildComponent {
  @Param cName: string = "cName"
  @Event changeNameCallback?: (name: string) => void

  build() {
    Column({space: 12}) {
      Text(`cName:${this.cName}`)
        .onClick(() => {
          if (this.changeNameCallback) {
            this.changeNameCallback(`${Date().toString()}`)
            console.log(`callback called in subcomponent: ${this.cName}`)
          }
        })
    }
  }
}

控制台输出

callback called in father component:Sun Mar 02 2025 09:39:27 GMT+0800
callback called in subcomponent: name

关键点

  • 同步机制:通过 @Event 修饰的回调方法修改父组件的值是立即生效的,但从父组件同步回子组件的过程是异步的。因此,在调用 @Event 方法后,子组件中的值不会立即更新。
  • 异步更新:这种设计避免了频繁的同步操作,提升了性能,但开发者需注意数据更新的时机。

四、总结

通过以上实践,我们可以得出以下结论:

  1. 事件传递@Event 提供了一种简洁的方式,用于在父子组件之间传递事件并同步数据。
  2. 灵活性@Event 支持修饰可选回调方法,增强了代码的灵活性。
  3. 异步更新:父组件状态的更新是立即生效的,但子组件的更新是异步的,开发者需注意数据同步的时机。

@Event 修饰器的引入,极大地简化了父子组件之间的数据同步和事件传递,提升了代码的可读性和可维护性。在实际开发中,合理使用 @Event 可以有效减少冗余代码,提高开发效率。

### 组件间通信方法及实现 在 HarmonyOS Next 开发中,组件间通信是构建复杂应用的关键部分。以下是一些常用的组件间通信方法及其具体实现。 #### 使用 `@Prop` 和 `@Link` 进行父子组件通信 在父子组件之间传递数据时,可以使用 `@Prop` 和 `@Link` 装饰器。`@Prop` 用于从父组件向子组件传递数据,而 `@Link` 用于从子组件向父组件传递数据。 **示例代码:** ```typescript // 父组件 @Component export struct ParentComponent { @State message: string = "Hello from parent" build() { Column() { Text("Parent Component") ChildComponent({ message: this.message, onMessageChange: (newMessage: string) => { this.message = newMessage }}) } } } // 子组件 @Component export struct ChildComponent { @Prop message: string @Link onMessageChange: (newMessage: string) => void build() { Column() { Text(`Message from parent: ${this.message}`) Button("Change Message") .onClick(() => { this.onMessageChange("New message from child") }) } } } ``` #### 使用 `Emitter` 进行跨组件通信 当需要在非父子关系的组件之间进行通信时,可以使用 `Emitter`。通过定义一个公共的 `Emitter` 实例,可以在不同组件之间发送和接收事件。 **示例代码:** ```typescript // 定义 Emitter 实例 import emitter from '@ohos.events' // 发送事件的组件 emitter.emit('event_name', { data: 'Some data' }) // 接收事件的组件 emitter.on('event_name', (event) => { console.log(`Received event: ${event.data}`) }) ``` #### 使用 `module_common` 组件进行组件化通信解耦 为了实现组件化通信解耦,可以使用 `module_common` 组件作为支撑业务组件、业务基础组件的基础。`module_common` 提供了多数业务组件需要的基本功能,并且统一了基础组件的版本号。 **示例代码:** ```typescript // module_common 组件 export default class CommonModule { static commonFunction() { console.log("Common function called") } } // 业务组件 import CommonModule from './module_common' Component export default struct BusinessComponent { build() { Button("Call Common Function") .onClick(() => { CommonModule.commonFunction() }) } } ``` #### 使用 `@Provide` 和 `@Consume` 进行跨层级组件通信 对于深层嵌套的组件结构,可以使用 `@Provide` 和 `@Consume` 装饰器来实现跨层级组件通信。`@Provide` 用于提供数据,而 `@Consume` 用于消费数据。 **示例代码:** ```typescript // 提供数据的组件 @Component export struct ParentComponent { @Provide provideData: string = "Provided data" build() { Column() { Text("Parent Component") ChildComponent() } } } // 消费数据的组件 @Component export struct ChildComponent { @Consume provideData: string build() { Column() { Text(`Consumed data: ${this.provideData}`) } } } ``` ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值