HarmonyOS鸿蒙Next中组件内的对象数组如何观察到变化?

HarmonyOS鸿蒙Next中组件内的对象数组如何观察到变化? 代码如下,都是在同一个页面内:

// TestPage.ets
[@Observed](/user/Observed)
class WeekInfo{
  text?: string;   
  value?: number;   
  selected?: boolean; 
}
@State dateInfo:WeekInfo[] = [
  { text: '一', value: 1, selected: false },
  { text: '二', value: 2, selected: false },
  { text: '三', value: 3, selected: false },
  { text: '四', value: 4, selected: false },
  { text: '五', value: 5, selected: false },
  { text: '六', value: 6, selected: false },
  { text: '日', value: 7, selected: false }
]
//TestPage.ets
ForEach(this.dateInfo, (item:WeekInfo) => {
  Button(item.text)
    // 根据selected改变颜色
    .backgroundColor(item.selected?this.buttonCheckedColor:this.buttonUnCheckedColor)
    .onClick(() => {
      item.selected = !item.selected
      console.log(`${item.text}`)
      if (item.selected) {
        console.log('true')
      }else {
        console.log('false')
      }
    })
},(item:WeekInfo) => item.text)

我要在当前的component中检测selected的变化,如何观察?使用@Observed装饰器和@ObjectLink装饰器只能在组件和组件之间传递数据使用吗?同一个组件内如何观察到?

当前代码是可以间断打印true和false,但是无法改变 backgroundColor 的颜色,这个如何解决呢??


更多关于HarmonyOS鸿蒙Next中组件内的对象数组如何观察到变化?的实战教程也可以访问 https://www.itying.com/category-93-b0.html

5 回复

【解决方案】

监听数组内对象属性变化可以通过@Observed配合@ObjectLink装饰符实现。@Observed用于类,标记类为可观察对象,系统自动生成代理类监听类内部嵌套对象属性的变化。@ObjectLink用于变量建立与[@Observed](/user/Observed)类实例的双向绑定,监听对象内部属性变化并触发UI更新。以下是详细实现逻辑代码:

[@Observed](/user/Observed)
class WeekInfo{
  text?: string;
  value?: number;
  selected?: boolean;

  constructor(text:string,value:number,selected:boolean) {
    this.text = text
    this.value = value
    this.selected = selected
  }
}
@Component
struct DateInfo{
  [@ObjectLink](/user/ObjectLink) dateInfo:WeekInfo
  buttonCheckedColor: ResourceColor = Color.Blue;
  buttonUnCheckedColor: ResourceColor = Color.Red;

  build(){
    Button(this.dateInfo.text)
    // 根据selected改变颜色
      .backgroundColor(this.dateInfo.selected?this.buttonCheckedColor:this.buttonUnCheckedColor)
      .onClick(() => {
        this.dateInfo.selected = !this.dateInfo.selected

        console.log(`${this.dateInfo.text}`)
        if (this.dateInfo.selected) {
          console.log('true')
        }else {
          console.log('false')
        }
      })
  }
}

@Entry
@Component
struct PageTest {
  @State dateInfos:WeekInfo[] = [
    new WeekInfo( '一', 1, false ),
    new WeekInfo( '二', 2, false ),
    new WeekInfo( '三', 3, false ),
    new WeekInfo( '四', 4, false ),
    new WeekInfo( '五', 5, false ),
    new WeekInfo( '六', 6, false ),
    new WeekInfo( '日', 7, false )
  ]

  build() {
    Column(){
      //TestPage.ets
      ForEach(this.dateInfos, (item:WeekInfo) => {
        DateInfo({dateInfo:item})
      },(item:WeekInfo) => item.text)
    }
  }
}

更多关于HarmonyOS鸿蒙Next中组件内的对象数组如何观察到变化?的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


好的谢谢,

可以使用ObeservedV2和@Trace来实现,参考文档:https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-new-observedv2-and-trace#trace装饰对象数组

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

在HarmonyOS鸿蒙Next中,组件内对象数组的变化可通过@Observed@Track装饰器实现响应式监听。@Observed装饰类,@Track装饰具体属性。当数组对象属性被修改时,UI自动更新。若需整体数组变更响应,使用@State修饰数组变量,结合数组API如splice()触发更新。

在HarmonyOS Next中,当直接修改对象数组元素属性时,UI不会自动刷新。这是因为@State装饰的数组只监听数组本身的引用变化,而不监听数组内部对象属性的变化。

解决方案:

  1. 使用数组重新赋值
.onClick(() => {
  // 创建新数组,修改对应元素的selected属性
  this.dateInfo = this.dateInfo.map((week, index) => 
    index === itemIndex ? {...week, selected: !week.selected} : week
  );
})
  1. 或者使用@Observed + @ObjectLink组合(虽然你提到在同一个组件内):
[@Observed](/user/Observed)
class WeekInfo {
  // ...
}

@Component
struct WeekButton {
  [@ObjectLink](/user/ObjectLink) item: WeekInfo
  
  build() {
    Button(this.item.text)
      .backgroundColor(this.item.selected ? buttonCheckedColor : buttonUnCheckedColor)
      .onClick(() => {
        this.item.selected = !this.item.selected
      })
  }
}

// 在父组件中使用
ForEach(this.dateInfo, (item: WeekInfo) => {
  WeekButton({ item: item })
}, (item: WeekInfo) => item.text)

推荐使用第一种方法,通过创建新数组来触发状态更新,这是最直接有效的解决方案。

回到顶部