Harmony 状态监听 @Monitor和@Computed

2025-06-24 22:04:59
106次阅读
0个评论

@Monitor与@Computed装饰器在ArkUI状态管理中的协同应用

一、装饰器概述

1. @Monitor装饰器

@Monitor是ArkUI状态管理V2中的核心装饰器,用于深度监听状态变量的修改:

  • 支持监听嵌套类属性、多维数组项和对象数组中的指定项变化
  • 能够获取变化前后的值进行比较
  • 支持同时监听多个属性变化
  • 适用于@ComponentV2装饰的自定义组件和@ObservedV2装饰的类

2. @Computed装饰器

@Computed是用于优化性能的计算属性装饰器:

  • 自动检测依赖属性的变化并重新计算
  • 计算结果会被缓存,减少重复计算开销
  • 只能装饰getter方法,不允许赋值操作
  • 解决UI多次重用属性导致的性能问题

二、协同工作机制

1. 数据流协同

@ObservedV2
class Temperature {
  @Trace celsius: number = 20;
  
  @Computed
  get fahrenheit(): number {
    return this.celsius * 9/5 + 32;
  }
  
  @Computed 
  get kelvin(): number {
    return (this.fahrenheit - 32) * 5/9 + 273.15;
  }
}

@Entry
@ComponentV2
struct TempView {
  @Local temp: Temperature = new Temperature();
  
  @Monitor('temp.kelvin')
  onTempChange(mon: IMonitor) {
    console.log(`Kelvin变化: ${mon.value()?.before} → ${mon.value()?.now}`);
  }
  
  build() {
    Column() {
      Button("增加温度")
        .onClick(() => this.temp.celsius++)
      
      Text(`摄氏: ${this.temp.celsius.toFixed(1)}℃`)
      Text(`华氏: ${this.temp.fahrenheit.toFixed(1)}℉`)
      Text(`开氏: ${this.temp.kelvin.toFixed(1)}K`)
    }
  }
}

2. 典型工作流程

  1. 基础状态变量(@Local/@Trace)变化
  2. 触发关联的@Computed属性重新计算
  3. @Monitor监听到计算属性变化
  4. 执行@Monitor回调中的业务逻辑
  5. 更新依赖这些属性的UI组件

三、实际应用场景

1. 购物车总价计算

@ObservedV2
class CartItem {
  @Trace price: number = 0;
  @Trace quantity: number = 1;
}

@ObservedV2
class ShoppingCart {
  @Type(CartItem)
  @Trace items: CartItem[] = [];
  
  @Computed
  get total(): number {
    return this.items.reduce((sum, item) => sum + (item.price * item.quantity), 0);
  }
  
  @Computed
  get hasDiscount(): boolean {
    return this.total > 1000;
  }
  
  @Monitor('total', 'hasDiscount')
  onCartUpdate(mon: IMonitor) {
    mon.dirty.forEach(path => {
      console.log(`${path} 变化: ${mon.value(path)?.before} → ${mon.value(path)?.now}`);
    });
  }
}

2. 表单验证

@ObservedV2
class UserForm {
  @Trace username: string = '';
  @Trace password: string = '';
  @Trace confirmPwd: string = '';
  
  @Computed
  get isValid(): boolean {
    return this.username.length >= 6 && 
           this.password.length >= 8 &&
           this.password === this.confirmPwd;
  }
  
  @Monitor('isValid')
  onValidChange(mon: IMonitor) {
    if (mon.value()?.now) {
      console.log('表单验证通过');
    }
  }
}

四、性能优化建议

  1. 计算复杂度控制:保持@Computed方法简洁,避免复杂运算
  2. 监听范围精确:只监听必要的属性,避免过度监听
  3. 避免循环依赖:防止@Computed属性间相互引用导致死循环
  4. 合理使用缓存:利用@Computed的缓存特性减少重复计算
  5. 异步操作分离:不在@Monitor回调中执行耗时操作

五、与V1装饰器对比

特性 @Watch(V1) @Monitor(V2)
监听目标 单个状态变量 多个状态变量
深度监听 仅第一层属性 支持深层嵌套
变化值获取 不支持 支持前后值
执行时机 属性变更后 属性变更后
装饰对象 回调方法名 回调方法本身

六、最佳实践

  1. 分层设计
// Model层
@ObservedV2
class DataModel {
  @Trace rawData: number[] = [];
  
  @Computed
  get processedData(): number[] {
    return this.rawData.map(x => x * 2);
  }
}

// ViewModel层
class ViewModel {
  model: DataModel = new DataModel();
  
  @Monitor('model.processedData')
  onDataUpdate(mon: IMonitor) {
    // 处理数据变化逻辑
  }
}

// View层
@ComponentV2
struct DataView {
  @Provide viewModel: ViewModel = new ViewModel();
  
  build() {
    // UI渲染
  }
}
  1. 类型安全
@ObservedV2
class TypedModel<T> {
  @Trace value: T;
  
  @Computed
  get formattedValue(): string {
    return String(this.value);
  }
}
  1. 调试技巧
@Monitor('someProperty')
debugMonitor(mon: IMonitor) {
  console.group('属性变化追踪');
  mon.dirty.forEach(path => {
    console.log(`路径: ${path}`);
    console.log('旧值:', mon.value(path)?.before);
    console.log('新值:', mon.value(path)?.now);
  });
  console.groupEnd();
}

结语

@Monitor和@Computed装饰器的协同使用为ArkUI应用提供了强大的状态管理能力。通过合理运用这两个装饰器,开发者可以实现:

  • 高效的数据变化监听
  • 自动化的计算属性更新
  • 精细化的UI更新控制
  • 清晰的代码结构分层

掌握它们的协同工作机制,能够显著提升应用性能和维护性,是开发高质量HarmonyOS应用的关键技能之一。

收藏00

登录 后评论。没有帐号? 注册 一个。