HarmonyOS 鸿蒙Next @ObjectLink装饰对象数组时,数组中的对象发生变化时无法更新UI

HarmonyOS 鸿蒙Next @ObjectLink装饰对象数组时,数组中的对象发生变化时无法更新UI 我有一个子组件需要接收一个对象数组,同时要根据对象数组的变化来更新UI,但是使用@ObjectLink装饰对象数组时,数组中的对象发生变化时无法更新UI,只能监听到数组的变化,数组内对象的变化无法监测

@Observed
export class AreaGridItem implements CustomType.AreaGridItem {
  id: string
  status: CustomType.AccessStatus
  opacity: number

  constructor(id: string, status: CustomType.AccessStatus, opacity: number) {
    this.id = id
    this.status = status
    this.opacity = opacity
  }
}

@Observed
export class AreaGridList extends Array<AreaGridItem> {
}

@Observed
export class Area implements CustomType.AreaItem {
  areaName: string
  rowsNum: number
  columnsNum: number
  gridArr: AreaGridList

  constructor(areaName: string, rowsNum: number, columnsNum: number, gridArr: AreaGridList) {
    this.areaName = areaName
    this.rowsNum = rowsNum
    this.columnsNum = columnsNum
    this.gridArr = gridArr
  }
}

@Observed
export class AreaList extends Array<Area> {
}

@Component
export default struct XGird {
  [@ObjectLink](/user/ObjectLink) @Watch("watchAreaList") areaList: AreaList

  watchAreaList(){
    console.log("areaList", JSON.stringify(this.areaList))
  }
}

@Entry
@Component
struct Urgent {
  @State areaList:AreaList = new AreaList()
  aboutToAppear(){
    //可以检测到数组的变化
    ['A','B','C','D'].forEach(item=>{
      this.areaList.push(new Area(item,5,5,new AreaGridList))
    })
    for (let i = 0;i < this.areaList.length ; i++){
      for (let j = 0; j < this.areaList[i].rowsNum * this.areaList[i].columnsNum; j++) {
        this.areaList[i].gridArr.push(new AreaGridItem(j.toString(),i+1,1))
      }
    }
  }
  build(){
     XGird({
        areaList:this.areaList,
     })
     //检测不到,UI没有更新
     Button("改变Grid数组对象的某个属性").onClick(()=>{ 
        this.areaList[0].gridArr = new AreaGridList()
     })
  }
}

更多关于HarmonyOS 鸿蒙Next @ObjectLink装饰对象数组时,数组中的对象发生变化时无法更新UI的实战教程也可以访问 https://www.itying.com/category-93-b0.html

6 回复

您好,请您通过在线提单进一步解决:https://developer.huawei.com/consumer/cn/support/feedback/#/,感谢您的反馈和支持。

更多关于HarmonyOS 鸿蒙Next @ObjectLink装饰对象数组时,数组中的对象发生变化时无法更新UI的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


只有数组的长度发生变化时才视为数组发生变化(内存地址改变),如果只是数组中的对象属性变化了,数组本身长度没变,所以这时不会触发重绘。我是这么理解的

如果依赖数组的变化的话,需要在单独定义一个变量,UI界面绑定这个变量,然后数组中的对象属性发生变化时,触发回调修改这个变量的值。

数组存放的是基础数据类型的话,数组元素改变用state跟link可以监听到,但是如果是对象数组,数组中的元素,对象属性发生改变的话,属于嵌套了。这种情况就监听不到。

ObjectLink 就是用来监听数组中对象值的改变的,

在HarmonyOS鸿蒙Next中,@ObjectLink装饰器用于建立组件与数据对象之间的双向绑定。当@ObjectLink装饰的对象数组中的对象发生变化时,UI无法自动更新的问题,通常是由于数组的引用未发生变化,导致框架未能检测到数据变化。

在鸿蒙Next中,@ObjectLink装饰器依赖于对象的引用变化来触发UI更新。如果数组中的对象属性发生变化,但数组本身的引用未变,框架无法感知到内部对象的变化,因此不会触发UI更新。

要解决这个问题,可以通过以下方式确保UI更新:

  1. 手动触发更新:在修改数组中的对象后,手动调用this.update()方法,强制组件重新渲染。

  2. 替换数组:修改数组中的对象后,创建一个新的数组并替换原数组,确保数组引用发生变化,从而触发UI更新。

  3. 使用@Observed装饰器:确保数组中的对象类使用了@Observed装饰器,这样当对象属性发生变化时,框架能够检测到变化并更新UI。

例如:

@Observed
class Item {
  name: string = '';

  constructor(name: string) {
    this.name = name;
  }
}

class ViewModel {
  items: Item[] = [new Item('item1'), new Item('item2')];

  updateItem(index: number, newName: string) {
    this.items[index].name = newName;
    // 手动触发更新
    this.update();
  }
}

@Entry
@Component
struct MyComponent {
  @ObjectLink items: Item[];

  build() {
    // UI布局
  }
}

在上述代码中,updateItem方法修改了数组中的对象属性,并手动调用this.update()来触发UI更新。

总之,确保数组或对象的引用发生变化,或手动触发更新,可以解决@ObjectLink装饰对象数组时UI不更新的问题。

回到顶部