一、引言

在鸿蒙应用开发中,状态管理是构建动态界面的核心。@Watch 装饰器提供了一种优雅的方式来监听状态变量的变化,并在变化发生时自动执行自定义逻辑。本文将深入介绍 @Watch 的核心特性、基本语法、使用示例以及最佳实践,帮助你更好地在鸿蒙应用开发中运用这一强大工具。

二、@Watch 装饰器概述

@Watch 是鸿蒙应用开发中用于监听状态变量变化的装饰器。当被装饰的状态变量发生改变时,它会自动触发开发者指定的回调函数,适用于日志记录、数据同步、动画触发等场景。

三、核心特性

  • 监听机制:基于严格相等(===)判断值是否变化,只有严格不相等时才触发回调。
  • 初始化不触发:组件首次初始化时不会调用 @Watch 回调,仅在后续状态改变时触发。
  • 同步执行:回调在属性变更后同步执行。
  • 适用范围:可监听 @State@Prop@Link@ObjectLink@Provide@Consume@StorageProp@StorageLink 等装饰器修饰的变量。

四、基本语法

@State @Watch('callbackName') count: number = 0;
  • 参数为字符串形式的回调函数名(需加引号)。
  • 回调函数可接收一个可选参数 propertyName,表示被监听的属性名。

五、使用示例

下面是一个完整的示例,展示了如何使用 @Watch 监听计数器和输入框的变化,并记录变化日志。

@Entry
@Component
struct WatchExample {
  @State @Watch('onCountChange') count: number = 0;
  @State @Watch('onInputChange') inputText: string = '';
  @State logs: string[] = [];

  onCountChange(propertyName: string) {
    const log = `${propertyName} 变为 ${this.count}`;
    console.info(log);
    this.logs = [...this.logs.slice(-4), log]; // 保留最近5条
  }

  onInputChange(propertyName: string) {
    const log = `${propertyName} 变为 "${this.inputText}"`;
    console.info(log);
    this.logs = [...this.logs.slice(-4), log];
  }

  build() {
    Column({ space: 16 }) {
      Row({ space: 12 }) {
        Button('-').onClick(() => this.count--)
        Text(`${this.count}`).fontSize(24).width(60).textAlign(TextAlign.Center)
        Button('+').onClick(() => this.count++)
      }

      TextInput({ text: this.inputText, placeholder: '输入内容' })
        .onChange((value: string) => this.inputText = value)

      Divider()
      Text('变化日志:').fontSize(20).fontWeight(FontWeight.Bold)
      Column({ space: 4 }) {
        ForEach(this.logs, (log: string, index: number) => {
          Text(log).fontSize(20).fontColor('#666')
        })
      }.alignItems(HorizontalAlign.Start)
    }.width('100%').padding(16)
  }
}

运行效果:

在这里插入图片描述

5.1 运行效果分析

  1. 计数器交互:点击 +- 按钮时,count 值发生变化,onCountChange 回调被触发,日志区会追加一条形如 count 变为 1 的记录。由于日志数组只保留最近 5 条,超出部分自动丢弃,避免日志区无限增长。

  2. 输入框实时监听:在输入框中键入任意文本时,inputText 变量随 onChange 事件同步更新,onInputChange 回调被触发,日志区显示 inputText 变为 "用户输入的内容"。每次输入都会触发一次回调,体现了 @Watch 的同步执行特性。

  3. 日志滚动效果:日志区使用 ForEach 循环渲染,当新日志加入时,数组引用发生变化([...this.logs.slice(-4), log]),驱动 UI 自动刷新。由于日志从旧到新排列,最新日志始终显示在列表底部,模拟了类似控制台日志的滚动效果。

  4. 性能表现:在正常交互频率下,@Watch 回调执行时间极短(微秒级),不会对 UI 渲染造成明显延迟。但在高频点击或快速输入场景下,建议对回调逻辑做轻量化处理,避免执行耗时操作。

六、注意事项

  • 避免无限循环:不要在 @Watch 回调中直接修改被监听的变量,否则会再次触发回调形成死循环。
  • 对象属性监听@Watch 仅监听引用变化,无法直接监听 @Observed 对象内部属性的变化。如需监听深层属性,可在子组件中使用 @ObjectLink 配合 @Watch
  • 高频场景防抖:在滑块、输入框等高频率变更场景,建议配合防抖(debounce)使用,避免频繁回调影响性能。

七、总结

@Watch 是鸿蒙应用开发中一个非常实用的装饰器,它让状态变化的监听变得简单而高效。通过合理运用 @Watch,你可以轻松实现日志记录、数据同步、动画触发等复杂逻辑,提升应用的用户体验。希望本文能帮助你更好地理解和应用 @Watch 装饰器。

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐