当前位置: 首页 > news >正文

鸿蒙5.0应用开发——V2装饰器@Monitor的使用

【高心星出品】

V2装饰器@Monitor的使用

概念

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

@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监听整个数组时,更改数组的某一项不会被监听到。无法监听内置类型(Array、Map、Date、Set)的API调用引起的变化。
  • 在继承类场景中,可以在父子组件中对同一个属性分别定义@Monitor进行监听,当属性变化时,父子组件中定义的@Monitor回调均会被调用。
  • 和@Watch装饰器类似,开发者需要自己定义回调函数,区别在于@Watch装饰器将函数名作为参数,而@Monitor直接装饰回调函数。@Monitor与@Watch的对比可以查看@Monitor与@Watch的对比。
特性@Monitor@Watch
监听深度支持深层属性监听仅第一层属性监听
多属性监听支持同时监听多个属性仅支持单个属性监听
新旧值获取提供变化前后的完整值无法获取旧值
回调触发机制多属性同事件变化合并触发每个属性变化独立触发
类属性监听需配合@ObservedV2和@Trace不支持类属性监听
  1. 深度监听能力

    • 支持监听嵌套类、多维数组、对象数组中指定项的变化(需配合@ObservedV2和@Trace使用)
    • 示例场景:监听用户信息对象中address.city属性的变化,仅当该属性修改时触发回调
  2. 多属性联合监听
    可同时监听多个属性变化,当多个属性在一次事件中共同变化时,仅触发一次回调:

    @Monitor('age', 'height')
    onRecordChange(monitor: IMonitor) {console.log(`年龄或身高变化:${this.age}, ${this.height}`);
    }
    
  3. 变化值追踪
    提供变化前后的值对比能力,通过monitor.value()?.beforemonitor.value()?.now访问新旧值

Imonitor接口说明

在鸿蒙ArkTS状态管理V2中,IMonitor 是配合 @Monitor 装饰器使用的核心接口,用于捕获和响应状态变量的细粒度变化。以下是关键特性和用法解析:


一、IMonitor 核心功能

  1. 变化路径追踪
    通过 monitor.dirty 获取所有触发回调的变量路径集合,适用于同时监听多个路径的场景:

    @Monitor('users.0.name', 'users.1.age')
    onChanges(monitor: IMonitor) {monitor.dirty.forEach((path: string) => {console.log(`路径 ${path} 发生变化`);});
    }
    
  2. 值变化对比
    monitor.value(path) 返回一个包含 beforenow 属性的对象,用于获取变化前后的值:

    const change = monitor.value('dimensionTwo.0.0');
    console.log(`旧值:${change?.before} → 新值:${change?.now}`);
    
  3. 路径动态解析
    支持多维数组和嵌套对象路径(如 array.0.property),要求路径必须与被 @Trace 装饰的属性严格匹配。

案例

monitor的基本使用:

下面案例monitor观察两个基本变量,当两个变量改变的时候,显示旧数据和新数据。

在这里插入图片描述

@Entry
@ComponentV2
struct Monitorpage {// 被观察的数据必须由@local @param或者@provider装饰@Local name: string = 'gxx'@Local age: number = 30@Local msg:string=''// 观察的变量要一一列举@Monitor('name','age')// Imonitor 中的dirty代表改变的变量名字,类型为数组// Imonitor 中的value代表该dirty对应的数据,包含旧数据和新数据ondatachange(data: IMonitor) {data.dirty.forEach((item: string) => {let before = data.value(item)?.before!let after = data.value(item)?.now!this.msg+=`${item} 旧数据:${before} 新数据:${after}\n`})}build() {Column({ space: 20 }) {Button('page name: ' + this.name).width('60%').onClick(() => {// 同时改变name和agethis.name = 'ggl'this.age += 1})Button('page age: ' + this.age).width('60%').onClick(() => {this.age += 1})Text(this.msg).fontSize(20)}.height('100%').width('100%')}
}

monitor观察复杂对象:

下面案例monitor观察的数据是复杂对象,需要使用@observed才能观察到属性的变化。

在这里插入图片描述

@ObservedV2
class user{@Trace name:string@Trace age:numberconstructor(name: string, age: number) {this.name = namethis.age = age}}@Entry
@ComponentV2
struct Monitorpage {// 被观察的数据必须由@local @param或者@provider装饰@Local u: user = new user('gxx',30)@Local msg:string=''// 观察对象U 属性改变不会引起刷新@Monitor('u.name','u.age')// Imonitor 中的dirty代表改变的变量名字,类型为数组// Imonitor 中的value代表该dirty对应的数据,包含旧数据和新数据ondatachange(data: IMonitor) {data.dirty.forEach((item: string) => {let before = data.value(item)?.before!let after = data.value(item)?.now!this.msg+=`${item} 旧数据:${before} 新数据:${after}\n`})}build() {Column({ space: 20 }) {Button('page name: ' + this.u.name).width('60%').onClick(() => {// 同时改变name和agethis.u.name = 'ggl'this.u.age += 1})Button('page age: ' + this.u.age).width('60%').onClick(() => {this.u.age += 1})Text(this.msg).fontSize(20)}.height('100%').width('100%')}
}

monitor观察数组元素和数组长度案例:

下面这个案例monitor将要观察的是数组元素和数组长度的变化。

在这里插入图片描述

@Entry
@ComponentV2
struct Monitorpage {// 被观察的数据必须由@local @param或者@provider装饰@Local nums:number[]=[1,2,3]@Local msg:string=''// 观察数组nums的元素nums.i和数组长度 nums.length@Monitor('nums.0','nums.length')// Imonitor 中的dirty代表改变的变量名字,类型为数组// Imonitor 中的value代表该dirty对应的数据,包含旧数据和新数据ondatachange(data: IMonitor) {data.dirty.forEach((item: string) => {let before = data.value(item)?.before!let after = data.value(item)?.now!this.msg+=`${item} 旧数据:${before} 新数据:${after}\n`})}build() {Column({ space: 20 }) {Button('page nums.0: ' + this.nums[0]).width('60%').onClick(() => {// 新增元素this.nums[0]=this.nums[0]+1this.nums.push(this.nums[this.nums.length-1]+1)})Button('page nums.1: ' + this.nums[1]).width('60%').onClick(() => {// 更新数据this.nums[1]=10})Text(this.msg).fontSize(20)}.height('100%').width('100%')}
}
http://www.dtcms.com/a/389179.html

相关文章:

  • 八、Java-XML
  • 计算机在医疗领域应用的独特技术问题分析
  • HTB Intentions writeup(SQL二次注入也是注入)
  • 第一章 预训练:让模型“博闻强识”
  • 【数组】求两个匀速运动质点的相交或最小距离
  • 新手向:Python爬虫原理详解,从零开始的网络数据采集指南
  • OKZOO进军HealthFi:承接AIoT,引领Health-to-Earn
  • Halcon 相机标定
  • 腾讯混元发布集成翻译模型Hunyuan-MT-Chimera-7B,已开放体验
  • mybatis-plus扩展
  • 从x.ai到VSCode:一个AI编程助手的意外之旅
  • SQLite vs MySQL:核心SQL语法差异全面解析
  • 【每日算法】两数相加 LeetCode
  • ActiveMQ底层原理与性能优化
  • Ceph IO流程分段上传(1)——InitMultipart
  • 大数据毕业设计选题推荐-基于大数据的农作物产量数据分析与可视化系统-Hadoop-Spark-数据可视化-BigData
  • 【回归之作】学校实训作业:Day04面向对象思想编程
  • Ubuntu20.04或者Ubuntu24.04 TypeC-连接屏幕不显示问题
  • 【SQLSERVER】SQL Server 表导出与导入
  • postgresql和mongodb谁的地位更高
  • RK3588+复旦微JFM7K325T工业控制解决方案
  • RabbitMQ全方位解析
  • 云望无人机图传原理,无人机图传方式哪种好
  • 无人机50公里遥控模块技术要点与难点
  • 【三维重建】Octree-GS:基于LOD的3DGS实时渲染(TPAMI2025)
  • 《深度拆解3D开放世界游戏中角色攀爬系统与地形碰撞网格动态适配的穿透卡顿复合故障》
  • 数据库mysql连接池:从原理到实践的全面解析
  • # 深入理解栈、栈帧与递归:从迭代与递归归并排序双视角解析
  • Django 完整项目开发:博客系统
  • FPGA部署视觉模型