鸿蒙应用开发之状态变化通知:@Watch 装饰器详解与实战

这是一个使用鸿蒙技术开发的本地原生记账应用,非常适合大家用来练手。相关源码已上传至 Github,点击此处查看项目。欢迎大家交流、指正,也欢迎提交 PR。

一、引言

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

二、@Watch 装饰器概述

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

三、核心特性

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

四、基本语法

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

五、使用示例

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

typescript 复制代码
@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 装饰器。

相关推荐
swipe1 小时前
13|(前端转全栈)支付成功不等于结束:回调、幂等、超时关单和状态竞争
前端·后端·面试
swipe1 小时前
12|(前端转全栈)点击提交订单后,后端如何用事务守住价格、库存和订单?
前端·后端·面试
小林ixn1 小时前
React + TypeScript 实战:从“类型体操”到“数据持久化”,一次讲透组件通信与副作用管理
前端·react.js·typescript
何时梦醒1 小时前
React + TypeScript 企业级开发实战:从零搭建到组件架构演进
前端·react.js·全栈
Coffeeee1 小时前
AGP9.0的主要变更项,给Gradle来一次大变样
android·前端·gradle
用户0934077735141 小时前
HarmonyOS WPS Open SDK 快速入门:HAR 装上就能打开文档吗
typescript·harmonyos
无人生还1 小时前
从 Vue3 到 React · 快速上手系列第 7 篇:副作用与生命周期 —— watch/watchEffect 如何翻译为 useEffect
前端·vue.js·react.js
熊猫钓鱼>_>1 小时前
ArkTS 基础入门:从零搭建第一个交互页面
华为·架构·交互·ts·harmonyos·arkts·鸿蒙
三声三视1 小时前
DevEco Code 让 AI 写 ArkTS,enum 反向查表真机翻车——我换成 typeof + as const 后清净了
人工智能·harmonyos·arkts·鸿蒙