news 2026/4/16 7:20:12

鸿蒙中级课程笔记2—状态管理V2—@Monitor装饰器:状态变量修改监听

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
鸿蒙中级课程笔记2—状态管理V2—@Monitor装饰器:状态变量修改监听

为了增强状态管理框架对状态变量变化的监听能力,开发者可以使用@Monitor装饰器对状态变量进行监听。

@Monitor提供了对V2状态变量的监听。在阅读本文档前,建议提前阅读:@ComponentV2,@ObservedV2和@Trace,@Local。

说明

@Monitor装饰器从API version 12开始支持。

从API version 12开始,该装饰器支持在元服务中使用。

概述

@Monitor装饰器用于监听状态变量修改,使得状态变量具有深度监听的能力:

  • @Monitor装饰器支持在@ComponentV2装饰的自定义组件中使用,未被状态变量装饰器@Local、@Param、@Provider、@Consumer、@Computed装饰的变量无法被@Monitor监听到变化。

  • @Monitor装饰器支持在类中与@ObservedV2、@Trace配合使用,不允许在未被@ObservedV2装饰的类中使用@Monitor装饰器。未被@Trace装饰的属性无法被@Monitor监听到变化。

  • 当观测的属性变化时,@Monitor装饰器定义的回调方法将被调用。判断属性是否变化使用的是严格相等(===),当严格相等判断的结果是false(即不相等)的情况下,就会触发@Monitor的回调。当在一次事件中多次改变同一个属性时,将会使用初始值和最终值进行比较以判断是否变化。

  • 单个@Monitor装饰器能够同时监听多个属性的变化,当这些属性在一次事件中共同变化时,只会触发一次@Monitor的回调方法。

  • @Monitor装饰器具有深度监听的能力,能够监听嵌套类、多维数组、对象数组中指定项的变化。对于嵌套类、对象数组中成员属性变化的监听要求该类被@ObservedV2装饰且该属性被@Trace装饰。

  • 当@Monitor监听整个数组时,更改数组的某一项不会被监听到(注意,@Monitor可以监听数组中某一项的变化)。无法监听内置类型(Array、Map、Date、Set)的API调用引起的变化。

  • 在继承类场景中,可以在父子组件中对同一个属性分别定义@Monitor进行监听,当属性变化时,父子组件中定义的@Monitor回调均会被调用。

  • 和@Watch装饰器类似,开发者需要自己定义回调函数,区别在于@Watch装饰器将函数名作为参数,而@Monitor直接装饰回调函数。@Monitor与@Watch的对比可以查看@Monitor与@Watch的对比。

状态管理V1版本@Watch装饰器的局限性

现有状态管理V1版本可以实现对对象、数组中某一单个属性或数组项变化的监听,但无法获取变化之前的值。例子参考状态管理V1版本@Watch装饰器的局限性代码示例

装饰器说明

@Monitor属性装饰器说明
装饰器参数字符串类型的对象属性名。可同时监听多个对象属性,每个属性以逗号隔开,例如@Monitor('prop1', 'prop2')。可监听深层的属性变化,如多维数组中的某一个元素,嵌套对象或对象数组中的某一个属性。详见监听变化。
装饰对象@Monitor装饰成员方法。当监听的属性发生变化时,会触发该回调方法。该回调方法以IMonitor类型的变量作为参数,开发者可以从该参数中获取变化前后的相关信息。

举例如下:

@Entry @ComponentV2 struct Index { @Local info: Info = new Info('Tom', 25); @Monitor('info') infoChange(monitor: IMonitor) { hilog.info(0xFF00, 'testTag', '%{public}s', `info change`); } @Monitor('info.name') infoPropertyChange(monitor: IMonitor) { let lastValue: string = monitor.value()?.before as string; let curValue: string = monitor.value()?.now as string; hilog.info(0xFF00, 'testTag', 'lastValue={lastValue}, currentValue={curValue}', `info name change`); } // 同时监听状态变量age和非状态变量name @Monitor('age', 'name') onPropertyChange(monitor: IMonitor) { monitor.dirty.forEach((path: string) => { hilog.info(0xFF00, 'testTag', '%{public}s', `property path:${path} change from ${monitor.value(path)?.before} to ${monitor.value(path)?.now}`); }) } } build() { Column() { Text(`name: ${this.info.name}, age: ${this.info.age}`) Button('change info') .onClick(() => { this.info = new Info('Lucy', 18); // 能够监听到 }) Button('change info.name') .onClick(() => { this.info.name = 'Jack'; // 监听不到 }) } } }

接口说明

IMonitor类型和IMonitorValue<T>类型的接口说明参考API文档:状态变量变化监听。

监听变化

例子参考状态管理V1版本@Watch装饰器的局限性代码示例

在@ComponentV2装饰的自定义组件中使用@Monitor

使用@Monitor监听的状态变量发生变化时,会触发@Monitor的回调方法。

  • @Monitor监听的变量需要被@Local、@Param、@Provider、@Consumer、@Computed装饰,未被状态变量装饰器装饰的变量在变化时无法被监听。@Monitor可以同时监听多个状态变量,这些变量名之间用","隔开。

  • @Monitor监听的状态变量为类对象时,仅能监听对象整体的变化。监听类属性的变化需要类属性被@Trace装饰。

在@ObservedV2装饰的类中使用@Monitor

使用@Monitor监听的属性发生变化时,会触发@Monitor的回调方法。

  • @Monitor监听的对象属性需要被@Trace装饰,未被@Trace装饰的属性的变化无法被监听。@Monitor可以同时监听多个属性,这些属性之间用","隔开。

  • @Monitor可以监听深层属性的变化,该深层属性需要被@Trace装饰。

  • 在继承类场景下,可以在继承链中对同一个属性进行多次监听。

通用监听能力

@Monitor还有一些通用的监听能力。

  • @Monitor支持对数组中的项进行监听,包括多维数组,对象数组。@Monitor无法监听内置类型(Array、Map、Date、Set)的API调用引起的变化。当@Monitor监听数组整体时,只能观测到数组整体的赋值。可以通过监听数组的长度变化来判断数组是否有插入、删除等变化。当前仅支持使用"."的方式表达深层属性、数组项的监听。
  • @Monitor监听对象中属性时,如果对象整体改变,但监听的属性不变时,不触发该属性的@Monitor回调。
  • 在一次事件中多次改变被@Monitor监听的属性,以最后一次修改为准。

使用限制

例子参考状态管理V1版本@Watch装饰器的局限性代码示例

使用@Monitor需要注意如下限制条件:

  • 不建议在一个类中对同一个属性进行多次@Monitor的监听。当一个类中存在对一个属性的多次监听时,只有最后一个定义的监听方法会生效。

  • 当@Monitor传入多个路径参数时,以参数的全拼接结果判断是否重复监听。全拼接时会在参数间加空格,以区分不同参数。例如,'ab', 'c'的全拼接结果为'ab c','a', 'bc'的全拼接结果为'a bc',二者全拼接不相等。以下示例中,Monitor 1、Monitor 2与Monitor 3都监听了name属性的变化。由于Monitor 2与Monitor 3的入参全拼接相等(都为'name position'),因此Monitor 2不生效,仅Monitor 3生效。当name属性变化时,将同时触发onNameAgeChange与onNamePositionChangeDuplicate方法。但请注意,Monitor 2与Monitor 3的写法仍然被视作在一个类中对同一个属性进行多次@Monitor的监听,这是不建议的。

  • @Monitor的参数需要为监听属性名的字符串,仅可以使用字符串字面量、const常量、enum枚举值作为参数。如果使用变量作为参数,仅会监听@Monitor初始化时,变量值所对应的属性。当更改变量时,@Monitor无法实时改变监听的属性,即@Monitor监听的目标属性从初始化时便已经确定,无法动态更改。不建议开发者使用变量作为@Monitor的参数进行初始化。

  • 建议开发者避免在@Monitor中再次更改被监听的属性,这会导致无限循环

@Monitor与@Watch对比

@Monitor与@Watch的用法、功能对比如下:

用法@Watch@Monitor
参数回调方法名。监听状态变量名、属性名。
监听目标数只能监听单个状态变量。能同时监听多个状态变量。
监听能力跟随状态变量观察能力(一层)。跟随状态变量观察能力(深层)。
能否获取变化前的值不能获取变化前的值。能获取变化前的值。
监听条件监听对象为状态变量。监听对象为状态变量或为@Trace装饰的类成员属性。
使用限制仅能在@Component装饰的自定义组件中使用。能在@ComponentV2装饰的自定义组件中使用,也能在@ObservedV2装饰的类中使用。

使用场景

例子参考状态管理V1版本@Watch装饰器的局限性代码示例

监听深层属性变化

@Monitor可以监听深层属性的变化,并能够根据更改前后的值做分类处理。

常见问题

例子参考状态管理V1版本@Watch装饰器的局限性代码示例

自定义组件中@Monitor对变量监听的生效及失效时间

当@Monitor定义在@ComponentV2装饰的自定义组件中时,@Monitor会在状态变量初始化完成之后生效,并在组件销毁时失效。

类中@Monitor对变量监听的生效及失效时间

当@Monitor定义在@ObservedV2装饰的类中时,@Monitor会在类的实例创建完成后生效,在类的实例销毁时失效。

@Monitor会在类的实例创建完成后生效,这个时机晚于类的constructor,早于自定义组件的aboutToAppear。

类中定义的@Monitor随着类的销毁失效。而由于类的实际销毁释放依赖于垃圾回收机制,因此会出现即使所在自定义组件已经销毁,类却还未及时销毁,导致类中定义的@Monitor仍在监听变化的情况。

借助垃圾回收机制去取消@Monitor的监听是不稳定的,开发者可以采用以下两种方式去管理@Monitor的失效时间:

1、将@Monitor定义在自定义组件中。由于自定义组件在销毁时,状态管理框架会手动取消@Monitor的监听,因此在自定义组件调用完aboutToDisappear,尽管自定义组件的数据不一定已经被释放,但@Monitor回调已不会再被触发。

2、主动置空监听的对象。当自定义组件即将销毁时,主动置空@Monitor的监听目标,这样@Monitor无法再监听原监听目标的变化,达到取消@Monitor监听的效果。举例如下:

aboutToDisappear(): void { hilog.info(0xFF00, 'testTag', '%{public}s', 'Child aboutToDisappear', this.infoWrapper.info?.age); this.infoWrapper.info = undefined; // 使InfoWrapper对info.age的监听失效 }

正确设置@Monitor入参

由于@Monitor无法对入参做编译时校验,当前存在以下写法不符合@Monitor监听条件但@Monitor仍会触发的情况。开发者应当正确传入@Monitor入参,不传入非状态变量,避免造成功能异常或行为表现不符合预期。

无法监听变量从可访问变为不可访问和从不可访问变为可访问

@Monitor仅会保存变量可访问时的值,当状态变量变为不可访问的状态时,并不会记录其值的变化。即不能监听属性从undefined | null变为正常值,也不能监听属性从正常值变为undefined | null

从API version 20开始,如果需要监听可访问到不可访问和不可访问到可访问的状态变化,可以使用addMonitor。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/10 11:31:19

AI人工智能-RAG方法-第十四周(小白)

一、RAG到底是什么? RAG是 Retrieval Augmengted Generation(检索增强生成)的缩写,核心逻辑特别好理解——就像我们写作文时,先查资料再动笔,而不是凭脑子硬记硬写。 简单说:AI回答问题时,不会只靠自己“记住”的知识,而是从外部文档库(或搜索引擎)里检索出和问题相…

作者头像 李华
网站建设 2026/4/14 10:54:19

深度测评!9款AI论文写作软件评测:本科生毕业论文全场景应对指南

深度测评&#xff01;9款AI论文写作软件评测&#xff1a;本科生毕业论文全场景应对指南 2026年AI论文写作工具测评&#xff1a;功能与效率的深度解析 随着人工智能技术的不断进步&#xff0c;AI论文写作工具逐渐成为本科生撰写毕业论文的重要辅助。然而&#xff0c;面对市场上…

作者头像 李华
网站建设 2026/4/14 14:26:20

经营分析师-《验证合理值》

经营分析师-《验证合理值》 前言&#xff1a; 在工作过程中&#xff0c;有一个环节的工作最常见&#xff0c;也最难做&#xff0c;那就是合理值到底应该是多少&#xff0c;怎么去判断合理值应该设置为多少&#xff0c;本次文章针对历史操作过内容进行分享&#xff0c;文末告知…

作者头像 李华
网站建设 2026/4/9 23:20:19

基于SHAP可解释性AI的支持向量机和K近邻工业轴承故障诊断特征贡献分析(Python,jupyter nootbook文件)

首先加载包含23个时域和频域特征的模拟振动数据集&#xff0c;这些特征模拟了真实轴承在健康、内圈故障、外圈故障和滚动体故障等不同状态下的振动特性。算法通过t-SNE降维技术可视化高维特征空间的数据分布&#xff0c;展示不同故障类型在二维空间的聚类情况。接着&#xff0c…

作者头像 李华