HarmonyOS鸿蒙Next中如何解决使用@State修饰对象数组,数据变化时页面不刷新问题
HarmonyOS鸿蒙Next中如何解决使用@State修饰对象数组,数据变化时页面不刷新问题
【问题现象】
使用@State修饰对象数组,直接修改对象的属性时,系统无法感知到变量的变化,造成页面无法渲染刷新。从下图中,可以观察到当我们直接修改对象数组中对象的属性时,虽然值已经修改成功了,但是页面并没有刷新。这是因为系统没有感知到数据的变化,导致界面没有渲染。
问题代码如下:
class PersonPre {
name: string;
age: number;
constructor(name: string, age: number) {
this.name = name;
this.age = age;
}
}
[@Entry](/user/Entry)
@Component
struct PrePage {
[@State](/user/State) persons: PersonPre[] = [
new PersonPre('小张', 12),
new PersonPre('小赵', 13),
new PersonPre('小李', 14),
new PersonPre('小王', 15),
]
build() {
Scroll() {
Column({space: 10}) {
ForEach(this.persons, (curPerson: PersonPre, index: number) => {
Column() {
Text(`姓名${curPerson.name}`)
.fontSize(20)
.fontWeight(FontWeight.Bold)
Text(`年龄${curPerson.age}`)
.fontSize(15)
.fontWeight(FontWeight.Regular)
}
})
Button('修改对象数组属性-修改小张年龄为66')
.onClick(() => {
this.persons[0].age = 66
console.log('当前小张的年龄为' + JSON.stringify(this.persons[0]))
})
Button('替换对象数组元素-修改小张年龄为88')
.onClick(() => {
this.persons.splice(0, 1, new PersonPre('小张', 88))
console.log('当前小张的年龄为' + JSON.stringify(this.persons[0]))
})
}
}
.height('100%')
.width('100%')
}
}
【定位思路】
装饰器仅能观察到第一层的变化,但是在实际应用开发中,应用会根据开发需要,封装自己的数据模型。对于多层嵌套的情况,比如二维数组,或者数组项class,或者class的属性是class,他们的第二层的属性变化是无法观察到的。
如果想要实现动态更新,需要使用@Observed/@ObjectLink装饰器,@ObjectLink和@Observed类装饰器用于在涉及嵌套对象或数组的场景中进行双向数据同步。
- @Observed用于嵌套类场景中,观察对象类属性变化,用于修饰类。
- @ObjectLink装饰器装饰的状态变量用于接收@Observed装饰的类的实例,和父组件中对应的状态变量建立双向数据绑定。注意:@ObjectLink装饰器不能在@Entry装饰的自定义组件中使用。
【解决方案】
1. 使用@Observed修饰类
代码示例如下:
[@Observed](/user/Observed)
class Person {
name:string;
age:number;
constructor(name:string, age:number) {
this.name= name;
this.age= age;
}
}
2. 自定义子组件(注意@ObjectLink装饰器不能在@Entry装饰的自定义组件中使用)
代码示例如下:
@Component
struct MyPerson {
[@ObjectLink](/user/ObjectLink) person: Person
build() {
Column() {
Text(`姓名${this.person.name}`)
.fontSize(20)
.fontWeight(FontWeight.Bold)
Text(`年龄${this.person.age}`)
.fontSize(15)
.fontWeight(FontWeight.Regular)
}
}
}
3. 在父组件中使用子组件
代码示例如下:
ForEach(this.persons, (curPerson: Person, index: number) => {
MyPerson({person: curPerson})
})
【总结】
@State装饰器仅能观察到第一层的变化。对于多层嵌套的情况,比如对象数组等,他们的第二层的属性变化是无法观察到的。@Observed装饰的类,可以观察到属性的变化;@ObjectLink装饰器装饰的状态变量用于接收@Observed装饰的类的实例,和父组件中对应的状态变量建立双向数据绑定。
更多关于HarmonyOS鸿蒙Next中如何解决使用@State修饰对象数组,数据变化时页面不刷新问题的实战教程也可以访问 https://www.itying.com/category-93-b0.html
更多关于HarmonyOS鸿蒙Next中如何解决使用@State修饰对象数组,数据变化时页面不刷新问题的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
使用@Observed修饰类,并通过@ObjectLink在子组件中绑定对象,以解决@State修饰对象数组时数据变化页面不刷新的问题
1. 使用@Observed修饰类
[@Observed](/user/Observed)
class Person {
name: string;
age: number;
constructor(name: string, age: number) {
this.name = name;
this.age = age;
}
}
2. 创建子组件并使用@ObjectLink绑定对象
@Component
struct MyPerson {
[@ObjectLink](/user/ObjectLink) person: Person
build() {
Column() {
Text(`姓名${this.person.name}`)
.fontSize(20)
.fontWeight(FontWeight.Bold)
Text(`年龄${this.person.age}`)
.fontSize(15)
.fontWeight(FontWeight.Regular)
}
}
}
3. 在父组件中使用子组件
ForEach(this.persons, (curPerson: Person, index: number) => {
MyPerson({person: curPerson})
})