鸿蒙应用开发之状态变化通知:@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 装饰器。

相关推荐
Csvn4 小时前
🔍 TypeScript `satisfies` 操作符:既要类型安全,又要推断的原始字面量类型
前端
Csvn4 小时前
🚦 手写 Promise 并发控制:如何优雅限制异步请求的并发数?
前端
gb42152875 小时前
python中Web应用服务器
开发语言·前端·python
默_笙5 小时前
💌 为了把"主题色"传给孙子组件,我翻了五层楼——直到遇见了 useContext
前端·javascript
颜进强5 小时前
04 - 一张图看懂 OpenSpec 变更的一生:从创建到归档
前端·后端·ai编程
the_answer5 小时前
JS 垃圾回收机制
前端
小KK_5 小时前
JS 事件循环从小白视角入门:宏任务、微任务与 async/await 一网打尽
前端·javascript
aloha_5 小时前
Linux服务器上指定目录的文件下载
前端
小雨青年6 小时前
【HarmonyOS 7 沉浸光感深度实战】10 通用组件封装与现有项目接入
华为·harmonyos
YM52e6 小时前
蒙特卡洛模拟器:鸿蒙 Canvas 上的大数定律与中心极限定理实证
华为·harmonyos