鸿蒙next中使用@Observed和@ObjectLink遇到的坑, 数据更新但UI没更新

1. 还原本次事故

首先定义bean, 并用@Observed修饰

ini 复制代码
@Observed
export class PackAudio {
  audioUrl: string = ""
  createdAt: string = ""
  duration: number = 0
  name: string = ""
  objectId: string = ""
  belong?: string
  sort: number = 0
  isPlaying: boolean = false
  isNew: boolean = false
  }

自定义PackAudioView组件, 并且用@ObjectLink修饰

scss 复制代码
import { PackAudio } from './PackAudio';

@Component
export struct PackAudioView {
  @ObjectLink item: PackAudio;
  @Prop index: number = 0;
  @Prop currentClickIndex: number = -1;
  ownerObjectId: string = '';
  onClickItem?: () => void;

  build() {
    Row() {
      Stack() {
        Text('' + (this.index + 1))
          .width(54)
          .height(65)
          .textAlign(TextAlign.Center)
          .fontSize(15)
      }

      Column() {
        Text(this.item.name).fontSize(15).maxLines(1).textOverflow({ overflow: TextOverflow.Ellipsis })
        Text(`时长: ${this.item.duration}`)
          .fontSize(12)
          .margin({ top: 4 })
      }.layoutWeight(1).alignItems(HorizontalAlign.Start)

    }.width("100%").height(65).onClick(() => {
      this.onClickItem!()
    }).backgroundColor(this.currentClickIndex === this.index ? Color.Grey : Color.White)
  }
}

让我们在主页使用它

typescript 复制代码
import { ToastUtil } from '@pura/harmony-utils';
import { PackAudio } from './PackAudio';
import { PackAudioView } from './PackAudioView';

@Entry
@Component
struct Index {
  @State message: string = 'Hello World';
  @State audios: Array<PackAudio> = [
    {
      audioUrl: 'https://www.baidu.com/img/PCtm_d9c8750bed0b3c7d089fa7d55720d6cf.png',
      createdAt: '2021-01-01',
      duration: 10,
      name: '测试1',
      objectId: '1',
      sort: 1,
      isPlaying: false,
      isNew: false
    },
    {
      audioUrl: 'https://www.baidu.com/img/PCtm_d9c8750bed0b3c7d089fa7d55720d6cf.png',
      createdAt: '2021-01-01',
      duration: 10,
      name: '测试2',
      objectId: '1',
      sort: 1,
      isPlaying: false,
      isNew: false
    },
    {
      audioUrl: 'https://www.baidu.com/img/PCtm_d9c8750bed0b3c7d089fa7d55720d6cf.png',
      createdAt: '2021-01-01',
      duration: 10,
      name: '测试3',
      objectId: '1',
      sort: 1,
      isPlaying: false,
      isNew: false
    },
  ]
  @State currentClickIndex: number = -1

  build() {
    Column() {
      Text("测试测试")
      List() {
        ForEach(this.audios, (item: PackAudio, index: number) => {
          ListItem() {
            PackAudioView({
              item: item,
              index,
              currentClickIndex: this.currentClickIndex,
              onClickItem: () => {
                item.name = `点击了: ${item.name}`
                this.currentClickIndex = index
                ToastUtil.showToast('点击了: ' + item.name)
              }
            })
          }
        })
      }
    }
    .height('100%')
    .width('100%')
  }
}

最后的结果就是, 虽然我们改变item.name的值, 但是UI确没有更新. 很诡异, 搞了很久, 最后阅读文档才发现必须要求new对象出来!

2. 修改

修改我们赋值的方式, 添加构造函数

ini 复制代码
@Observed
export class PackAudio {
  audioUrl: string = ""
  createdAt: string = ""
  duration: number = 0
  name: string = ""
  objectId: string = ""
  belong?: string
  sort: number = 0
  isPlaying: boolean = false
  isNew: boolean = false

  constructor(audioUrl: string, createdAt: string, duration: number, name: string, objectId: string, belong?: string, sort: number = 0, isPlaying: boolean = false, isNew: boolean = false) {
    this.audioUrl = audioUrl
    this.createdAt = createdAt
    this.duration = duration
    this.name = name
    this.objectId = objectId
    this.belong = belong
    this.sort = sort
    this.isPlaying = isPlaying
    this.isNew = isNew
  }
}

然后我们赋值的时候用new出来

typescript 复制代码
import { ToastUtil } from '@pura/harmony-utils';
import { PackAudio } from './PackAudio';
import { PackAudioView } from './PackAudioView';

@Entry
@Component
struct Index {
  @State message: string = 'Hello World';
  @State audios: Array<PackAudio> = [
    new PackAudio(
      'https://www.baidu.com/img/PCtm_d9c8750bed0b3c7d089fa7d55720d6cf.png',
      '2021-01-01',
      10,
      '测试1',
      '1',
      "2",
      1,
      false,
      false
    ),
  ]
  @State currentClickIndex: number = -1

  build() {
    Column() {
      Text("测试测试")
      List() {
        ForEach(this.audios, (item: PackAudio, index: number) => {
          ListItem() {
            PackAudioView({
              item: item,
              index,
              currentClickIndex: this.currentClickIndex,
              onClickItem: () => {
                item.name = `点击了: ${item.name}`
                this.currentClickIndex = index
                ToastUtil.showToast('点击了: ' + item.name)
              }
            })
          }
        })
      }
    }
    .height('100%')
    .width('100%')
  }
}

这样就完美解决了...所以当我们从服务器获取到数据的array后, 也不能直接使用? 还需要new一次, 赋值? 搞不懂这是什么原理, 有懂的大佬可以留言

相关推荐
龙儿筝1 分钟前
ArkUI-X与Android桥接通信之消息通信
harmonyos
陈奕昆12 分钟前
5.1 HarmonyOS NEXT系统级性能调优:内核调度、I/O优化与多线程管理实战
华为·harmonyos
libo_20252 小时前
HarmonyOS5 全球化运营:使用AGC的本地化工具适配30+国家/地区
harmonyos
程序员小刘2 小时前
如何优化React Native应用以适配HarmonyOS5?
javascript·react native·react.js·华为·harmonyos
程序员小刘3 小时前
【HarmonyOS 5】拍摄美化开发实践介绍以及详细案例
华为·harmonyos
王二蛋与他的张大花3 小时前
HarmonyOS运动开发:打造你的专属运动节拍器
harmonyos
HarmonyOS_SDK4 小时前
钉钉携手鸿蒙扫一扫,打造高效办公新体验
harmonyos
__Benco7 小时前
OpenHarmony平台驱动使用(十五),SPI
人工智能·驱动开发·harmonyos
暗雨7 小时前
封装一个 auth 工具
harmonyos