HarmonyOS鸿蒙Next中通过class-transformer解析为一个泛型类的对象后,@ObservedV2修饰类中被@Trace修饰的变量改变后不会刷新

HarmonyOS鸿蒙Next中通过class-transformer解析为一个泛型类的对象后,@ObservedV2修饰类中被@Trace修饰的变量改变后不会刷新

这是实体类:

class BaseEntity<T>{
  code:number
  message:string
  body:T|undefined

  constructor(code: number, message: string, body: T | undefined) {
    this.code = code;
    this.message = message;
    this.body = body;
  }

}

[@ObservedV2](/user/ObservedV2)
class UserV2 {
  id: number
  [@Trace](/user/Trace) username: string
  [@Trace](/user/Trace) age: number

  constructor(id: number,username: string,age:number) {
    this.id = id;
    this.username = username;
    this.age = age
  }
}

这个在ts中通过class-transformer解析json字符串

export function parseJsonToClass<T>(jsonString: string, classType: new (...args: any[]) => T): T {
  const jsonObj = JSON.parse(jsonString);
  return plainToInstance(classType, jsonObj);
}

解析不是泛型类型的,修改user对象被@Trace 装饰的变量可以刷新UI:

@Local 
user:UserV2 = new UserV2(0,'',0)
  
aboutToAppear(): void {
  let json = '{"id": 1, "username": "alice", "age":5}';
  this.user = parseJsonToClass<UserV2>(json,UserV2)
}

但是解析的是泛型类型的,修改user对象被@Trace 装饰的变量就不能刷新UI了

let jsonStr = '{"code":0,"message":"success","body":{"id": 1, "username": "alice","age":5}}';
let entity = parseJsonToClass<BaseEntity<UserV2>>(jsonStr,BaseEntity)
Logger.info(JSON.stringify(entity.body))
if(entity.body){
  this.user = entity.body
}

更多关于HarmonyOS鸿蒙Next中通过class-transformer解析为一个泛型类的对象后,@ObservedV2修饰类中被@Trace修饰的变量改变后不会刷新的实战教程也可以访问 https://www.itying.com/category-93-b0.html

5 回复

使用@ObservedV2@Trace装饰器的类,需通过new操作符实例化后,才具备被观测变化的能力。

https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-new-observedv2-and-trace# 概述

可以先解析body,然后再把body设置到这个BaseEntity中去

在这ts的文件新增一个解析的方法:

/**
 * 
 * @param jsonString     json字符串
 * @param classType      json最终转换成的class类型
 * @param bodyName       body(泛型)字段的名称
 * @param bodyClassType  body(泛型)的class类型
 * @returns 
 */
export function parseJson<T,V>(jsonString: string, classType:ClassConstructor<T>,bodyName:string,bodyClassType:ClassConstructor<V>):T{
  const jsonObj = JSON.parse(jsonString);
  const jsonBodyObj = jsonObj[bodyName];
  //先解析body这个泛型对象
  const body:V = plainToInstance(bodyClassType,jsonBodyObj);
  //再解析整个,排除body字段
  const result:T = plainToInstance(classType, jsonObj,{excludePrefixes:[bodyName]});
  result[bodyName] = body
  return result;
}

调用:

let entity = parseJson<BaseEntity<UserV2>,UserV2>(jsonStr,BaseEntity,'body',UserV2)
Logger.info(JSON.stringify(entity.body))
if(entity.body){
  this.user = entity.body
}

更多关于HarmonyOS鸿蒙Next中通过class-transformer解析为一个泛型类的对象后,@ObservedV2修饰类中被@Trace修饰的变量改变后不会刷新的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


还有个办法,当转换包含嵌套对象的对象时,需要使用@Type装饰器指定嵌套对象的类型,但是这个类型是泛型 T //T是泛型这里会报错

但是class-transformer 还可以动态的配置Type:

const targetMap:TargetMap = {
  target:BaseEntity,
  properties: {
    'body':UserV2
  },
};
let entity =plainToInstance<BaseEntity<UserV2>,ESObject>(BaseEntity,JSON.parse(jsonStr),{targetMaps:[targetMap]})
Logger.info(JSON.stringify(entity.body))//可以打印一下,被@Trace修饰的字段名称是以__ob_为开头, 证明是成功的

我觉得这种方式更好一些,灰常感谢!!,

在HarmonyOS鸿蒙Next中,@ObservedV2用于标记可观察的类,@Trace用于标记需要跟踪的变量。当通过class-transformer解析为泛型类对象后,@Trace修饰的变量改变时,@ObservedV2修饰的类不会自动刷新。这是因为class-transformer生成的实例可能未正确绑定到鸿蒙的响应式系统中,导致状态更新未触发UI刷新。

在HarmonyOS Next中,当使用class-transformer解析泛型类时,@ObservedV2@Trace的响应式机制可能会失效。这是因为:

  1. 泛型类型在运行时会被擦除,导致plainToInstance无法正确保留UserV2的装饰器信息

  2. 解决方案建议:

  • 直接使用具体类型而非泛型进行转换

  • 在赋值前手动创建新的UserV2实例:

    if(entity.body){
      this.user = new UserV2(entity.body.id, entity.body.username, entity.body.age)
    }
    
  1. 或者为BaseEntity添加@ObservedV2装饰器:
[@ObservedV2](/user/ObservedV2)
class BaseEntity<T>{
  //...
}

这样可以确保响应式系统能正确追踪嵌套对象的变化。

回到顶部