问题现象
如下代码点击增加元素或减少元素,增加或减少嵌套在对象中的数组元素,界面不会有变化。
界面代码如下:
@Entry
@Component
struct Index {
@State dataList :TestDataList = new TestDataList([]);
aboutToAppear() {
this.dataList.datas = [new TestData('0',0),new TestData('1',1)];
}
build() {
Column(){
ForEach(this.dataList.datas,(data:TestData)=>{
Text(data.getName());
})
Button('增加元素').onClick((e)=>{
this.dataList.datas.push(new TestData(this.dataList.datas.length+'',this.dataList.datas.length));
}).width('100%')
Button('减少元素').onClick((e)=>{
this.dataList.datas.pop();
}).width('100%')
}.height('100%')
.alignItems(HorizontalAlign.Center)
.justifyContent(FlexAlign.Start)
}
}
数据类如下:
@Observed
export class TestData {
public value : number;
public name : string;
constructor(name: string, value: number) {
this.name = name;
this.value = value;
}
getValue():number{
return this.value + 100;
}
getName(): string {
return `name is: ${this.name} value is ${this.getValue()}`;
}
}
export class TestDataList {
public datas: Array<Object>
constructor(datas: Array<Object>) {
this.datas = datas;
}
}
可能原因
以上代码引起不刷新的问题主要是由于嵌套结构导致的:TestDataList这个类中嵌套存放了一个数组,数组中存放了一个类结构TestData。
由于@State装饰的变量,只能监听到对象本身的地址以及第一层属性的地址变化,也就是
由于this.dataList.datas.push、pop的操作不会触发dataList以及datas的地址变化,也就不会触发UI的刷新。
解决措施
解决方案是利用ArkUI提供的@Observed、@ObjectLink来对嵌套的结构建立UI与数据的联系,对于数组结构需要通过@Observed包装一层,使其成为可监听结构;
具体方案如下:
将Array变为ObseredArray,使用Observed监听。
替换原来的Array为ObseredArray。
视图中列表部分创建一个新的组件ListDataView,用ObjectLink接受数据。
原来的Index引入ListDataView使用,并传递参数。