HarmonyOS鸿蒙Next中使用@ObservedV2和@Trace装饰数组,数组中的对象的属性发生变化时,监听不到数组变化
HarmonyOS鸿蒙Next中使用@ObservedV2和@Trace装饰数组,数组中的对象的属性发生变化时,监听不到数组变化 使用@ObservedV2和@Trace装饰数组,数组中的对象的属性发生变化时,监听不到数组变化
@Monitor监听数组整体时,只能观测到数组整体的赋值。可以通过监听数组的长度变化来判断数组是否有插入、删除等变化
demo示例参考
let nextId: number = 0;
[@ObservedV2](/user/ObservedV2)
class Personon {
[@Trace](/user/Trace) age: number = 0;
constructor(age: number) {
this.age = age;
}
}
[@ObservedV2](/user/ObservedV2)
class Info {
id: number = 0;
[@Trace](/user/Trace) PersononList: Personon[] = [];
// 能够监听到infoArr的长度变化
[@Monitor](/user/Monitor)("PersononList.length")
onPersononListChange(monitor: IMonitor) {
console.info(`PersononList change from ${monitor.value()?.before} to ${monitor.value()?.now}`);
}
// 能够监听到整体赋值的变化
[@Monitor](/user/Monitor)("PersononList")
onInfoArrChange(monitor: IMonitor) {
console.log(`PersononList change`);
}
}
@Entry
@ComponentV2
struct Page241012094106027 {
info: Info = new Info();
aboutToAppear(): void {
for (let index = 0; index < 3; index++) {
this.info.PersononList.push(new Personon(index + 1))
}
}
build() {
Column() {
Button("change PersononList")
.onClick(() => {
this.info.PersononList = [new Personon(0)];
})
Button("change length")
.onClick(() => {
this.info.PersononList.push(new Personon(123))
})
Divider()
if (this.info.PersononList.length >= 3) {
Text(`${this.info.PersononList[0].age}`)
.fontSize(40)
.onClick(() => {
this.info.PersononList[0].age++;
})
}
Divider()
ForEach(this.info.PersononList, (item: Personon, index: number) => {
Text(`${index} ${item.age}`)
.fontSize(40)
})
Divider()
Index3()
}
}
}
@ComponentV2
struct Index3 {
data: Data = new Data();
build() {
Column() {
Button("change name")
.onClick(() => {
this.data.name = "Jack"; // 能够触发onNameChange方法
})
Text(`name:${this.data.name}`)
TextInput({ text: $$this.data.text })
Text(this.data.text)
}
}
}
[@ObservedV2](/user/ObservedV2)
class Data {
[@Trace](/user/Trace) name: string = "Tom";
[@Trace](/user/Trace) text: string = '0'
// name被[@Trace](/user/Trace)装饰,能够监听变化
[@Monitor](/user/Monitor)("name")
onNameChange(monitor: IMonitor) {
console.info(`name change from ${monitor.value()?.before} to ${monitor.value()?.now}`);
}
[@Monitor](/user/Monitor)("text")
onTextChange(monitor: IMonitor) {
console.info(`Text change from ${monitor.value()?.before} to ${monitor.value()?.now}`);
}
}
建议提供下可运行demo,方便这面调试用例, 数组那面添加数据 是否有new 关键字, push(new (object))
下面做了下测试正常,可参考:
[@ObservedV2](/user/ObservedV2)
class Personon {
[@Trace](/user/Trace) age: number = 0;
constructor(age: number) {
this.age = age;
}
}
[@ObservedV2](/user/ObservedV2)
class Info {
id: number = 0;
[@Trace](/user/Trace) PersononList: Personon[] = [];
// 能够监听到infoArr的长度变化
[@Monitor](/user/Monitor)("PersononList.length")
onPersononListChange(monitor: IMonitor) {
console.info(`PersononList change from ${monitor.value()?.before} to ${monitor.value()?.now}`);
}
// 能够监听到整体赋值的变化
[@Monitor](/user/Monitor)("PersononList")
onInfoArrChange(monitor: IMonitor) {
console.log(`PersononList change`);
}
}
@Entry
@ComponentV2
struct Page241012094106027 {
info: Info = new Info();
aboutToAppear(): void {
for (let index = 0; index < 3; index++) {
this.info.PersononList.push(new Personon(index + 1))
}
}
build() {
Column() {
Button("change PersononList")
.onClick(() => {
this.info.PersononList = [new Personon(0)];
})
Button("change length")
.onClick(() => {
this.info.PersononList.push(new Personon(123))
})
Divider()
if (this.info.PersononList.length >= 3) {
Text(`${this.info.PersononList[0].age}`)
.fontSize(40)
.onClick(() => {
this.info.PersononList[0].age++;
})
}
Divider()
ForEach(this.info.PersononList, (item: Personon, index: number) => {
Child({item:item})
})
}
}
}
@ComponentV2
struct Child {
@Param @Require item: Personon;
build() {
Row() {
Text(`${this.item.age}`)
.fontSize(40)
}
}
}
查下下面。可能哪个细节没有留意到,若自查还无法处理,请提供demo(不复杂,很快可以封装个demo,在我们提供的demo示例直接复制代码修改成自己的页面结构即可)
1.被@Trace装饰器装饰的属性property变化时,仅会通知property关联的组件进行刷新。
2.在嵌套类中,嵌套类中的属性property被@Trace装饰且嵌套类被@ObservedV2装饰时,才具有触发UI刷新的能力。
3.在继承类中,父类或子类中的属性property被@Trace装饰且该property所在类被@ObservedV2装饰时,才具有触发UI刷新的能力。
4.在@ObservedV2装饰的类中,只有被@Trace装饰的属性才可以用在UI中,未被@Trace装饰的属性不可以用在UI中。
更多关于HarmonyOS鸿蒙Next中使用@ObservedV2和@Trace装饰数组,数组中的对象的属性发生变化时,监听不到数组变化的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
我遇到同样的问题,自己写的demo,使用new关键字时候可以监听到变化,但是服务器返回的json数据解析为class 就无法检测到变化,看文档应该是是使用@Sendable注解,但是我试过了还是不行,不知道哪里的问题
在HarmonyOS鸿蒙Next中,@ObservedV2 和 @Trace 是用于数据绑定的装饰器。当使用 @ObservedV2 和 @Trace 装饰数组时,如果数组中的对象属性发生变化,系统可能无法直接监听数组的变化。这是因为 @ObservedV2 和 @Trace 主要关注的是数组的引用变化,而不是数组内部对象属性的变化。
@ObservedV2 用于标记一个类,使其成为可观察对象,而 @Trace 用于标记类中的属性,使其在变化时触发UI更新。当数组中的对象属性发生变化时,由于数组本身的引用未发生变化,@ObservedV2 和 @Trace 不会触发更新。
要解决这个问题,可以手动通知系统数组发生了变化。可以通过调用 this.array = [...this.array] 来重新设置数组的引用,强制触发UI更新。或者,可以在对象属性变化时,手动调用 this.array.splice(index, 1, updatedObject),这样也能触发数组的更新。
总之,@ObservedV2 和 @Trace 不会自动监听数组内部对象属性的变化,需要通过手动操作数组引用来触发更新。
在HarmonyOS鸿蒙Next中,使用@ObservedV2和@Trace装饰数组时,如果数组中的对象属性发生变化而监听不到数组变化,可能是因为@ObservedV2和@Trace的监听机制是基于数组引用变化而非数组内部对象属性变化。要解决这个问题,可以尝试以下方法:
-
手动通知更新:在修改数组内部对象属性后,手动调用
this.array = [...this.array],强制触发数组引用变化。 -
使用嵌套装饰:为数组中的对象也添加@ObservedV2装饰器,确保对象属性变化能被监听到。
通过这些方法,可以确保数组内部对象属性的变化能够被正确监听和响应。

