HarmonyOS 鸿蒙Next @Observed和@ObjectLink能更新数据,但是ForEach无法更新渲染

HarmonyOS 鸿蒙Next @Observed@ObjectLink能更新数据,但是ForEach无法更新渲染

我定义了一个用@Observed修饰的类:

class ChildData{
  ChildText?: string
  ChildImage?: Array<string>
  ChildUrl?: Array<string>
  Children?: Array<ChildData>

  constructor(ChildText?: string,ChildImage?: Array<string>,ChildUrl?: Array<string>,Children?: Array<ChildData>) {
    this.ChildText = ChildText
    this.ChildImage = ChildImage
    this.ChildUrl = ChildUrl
    this.Children = Children
  }
}

然后在一个自定义组件里专门嵌套:

@Component
struct ChildTag{
  @Consume opa: number
  @Consume fontSize: number
  [@ObjectLink](/user/ObjectLink) Children: ChildData

  build(){
    Row(){
      Text(this.Children.ChildText).width(100).fontSize(this.fontSize).backgroundColor(Color.Transparent).border({ width: 1, color: 0x3AB7C1, radius: 10, style: BorderStyle.Solid })
      Button({type: ButtonType.Circle, stateEffect:true}){
        Image($r('app.media.ic_public_list_add_light'))
          .height('24vp')
          .width('24vp')
      }
      .height('24vp')
      .width('24vp')
      .backgroundColor(0xf1f3f5)
      .opacity(this.opa)
      .animation({duration:100})
      .onClick(() => {
        this.Children.Children.push(new ChildData('tagtest', [], [], []))
      })
      Column(){
        ForEach(this.Children.Children, (item: ChildData, index: number) => {
          ChildTag({ Children: this.Children.Children[index] })
        }, (item: string, index: number) => item + index.toString())
      }
    }
  }
}

但是这个ForEach它只有首次渲染的时候是正常的,后续点击按钮数据源是更新了,但是渲染不更新

有没有佬看看我哪里没注意没写好


更多关于HarmonyOS 鸿蒙Next @Observed和@ObjectLink能更新数据,但是ForEach无法更新渲染的实战教程也可以访问 https://www.itying.com/category-93-b0.html

17 回复

@Observed class TestUnit{ name:string=’’

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

@Observed class FormTest extends Array<TestUnit> {

constructor() { super() this.addList(‘test-1’)

} addList(name:string){ this.push(new TestUnit(name))

} }

@Component struct Test { @ObjectLink form:FormTest count:number=1 build() { Column(){ Text(‘title’).onClick(()=>{ this.form.addList(‘test-’+(++this.count)) console.log(’’+this.form.length) }) List(){ ForEach(this.form,(item:TestUnit)=>{ ListItem(){ TextInput({text:item.name}).onChange((value:string)=>{ item.name=value }) }.width(‘80%’).height(40) },(item:TestUnit,index)=>‘Test-’+index) }.width(‘100%’).height(‘85%’) }.width(‘100%’).height(‘100%’) } } @Entry @Component struct Second { @State forms:FormTest[]=[new FormTest()] build() { List(){ ForEach(this.forms,(item:FormTest,index:number)=>{ ListItem(){ Test({form:this.forms[index]}) }.width(‘100%’).height(100) },(item:FormTest,index:number)=>‘form-test-’+index) }.width(‘100%’).height(‘100%’) } }

更多关于HarmonyOS 鸿蒙Next @Observed和@ObjectLink能更新数据,但是ForEach无法更新渲染的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


  • 第一,第二层数组一定要用extend
  • 第二,对于ObjectLink,传入时候不能用foreach循环出来的item,而是要用数组的index来获取,不过这个只影响提示不影响具体使用

我这个里面的数组类型也是要嵌套同样自定义的对象,就是A里面的数组a也是Array,也是extend么?

谢谢,已经理解用法了,

这个UI刷新机制,真的是呵呵。想吐。

迭代了几次api好像好些了😂,

麻烦各位大佬帮忙看下, 数据第一次请求时, 数据和UI都发生变化, 当activeIndex发生变化时, 数据变化了, 但是UI没有更新,这个怎么解决

我也遇到这样的问题了,无法渲染:

以下是源代码:

@Preview
@Component
export default struct Watching {
  @State isEdit: boolean = false;
  @State isDisableDelete: boolean = false;
  @State isSelected: boolean = false;
  @State history: History[] = [];
  async aboutToAppear(){
    let str = await pref.getValue(CommonConstants.HISTORY,CommonConstants.HISTORY,'') as string;
    console.log('fred',`获取收藏:str=${str}`)
    this.history = JSON.parse(str) as History[];
    this.history = this.history.filter(item => item.type == cacheType.favorite);
  }
  build() {
    Column() {
      //编辑
      Row() {
        Row({ space: 8 }) {
          Text(!this.isEdit ? '编辑' : '退出').myWhiteFont()
          Image(!this.isEdit ? $r('app.media.edit') : $r('app.media.cross')).width(18).height(18).fillColor(Color.White)
        }.onClick(() => this.isEdit = !this.isEdit)
      }.width('100%').justifyContent(FlexAlign.End).height(50).padding({ right: 10 })
      //list表
      Row() {
        List({ space: 10 }) {
          ForEach(this.history, ( item:History) => {
            ListItem() {
              Stack({ alignContent: Alignment.TopEnd }) {
                Column({ space: 6 }) {
                  Image(item.coverImgUrl).width(113).height(185)
                  Text(item.title).myWhiteFont()
                  Text(`观看至${item.index}集`).fontColor(Color.Gray)
                }
                if (this.isEdit) {
                  Image(item.isSelected ? $r('app.media.selected') : $r('app.media.select'))
                    .width(30)
                    .height(30)
                    .onClick(() =>{
                      item.isSelected = !item.isSelected;
                    })
                }
              }
            }
          },(item:History) => item.id.toString())
        }.lanes(3).alignListItem(ListItemAlign.Center)
      }.width('100%').padding(6)

      Blank()
      //操作按钮
      if (this.isEdit) {
        Row() {
          Button('全选').myButton().onClick((event: ClickEvent) => {

          })
          Button('删除').myButton().onClick((event: ClickEvent) => {

          }).enabled(this.isDisableDelete).fontColor(this.isDisableDelete ? Color.White : Color.Gray)
        }.width('100%')
      }
    }.width('100%').height('100%')
    .linearGradient({ angle: GradientDirection.Top, colors: [['#0F0F0F', 0.0], ['#3B1B1C', 0.6], ['#3B1B1C', 1.0]] })
  }
}

学习,

prop,link 只能同步基本数据类型,如果是数组对象比如

```typescript
[@Observed](/user/Observed)
objBean {
  title:string;
}

A{
  [@State](/user/State) obj:objBean[];
  build(){
    B({obj:$obj})
  }
}
B{
  [@ObjectLink](/user/ObjectLink) obj;
}

这样B能拿到么

你要拿到什么,你这段代码可以理解成想拿整个数组或者想拿数组里面的单个,

拿整个数组,

基本信息

  • 项目名称: 示例项目
  • 项目状态: 进行中
  • 项目负责人: 张三

能,但不能这么写。你得是个二维数组objBean[][], 然后把objBean[0]传进去,

巧了,我刚回答了另一个问题跟你一样的。https://docs.openharmony.cn/pages/v4.0/zh-cn/application-dev/quick-start/arkts-observed-and-objectlink.md#%E4%BA%8C%E7%BB%B4%E6%95%B0%E7%BB%84

这个文档二维数组部分需要每个字认真读一下,在对照着我的例子,就可以解决问题了

首次渲染用的是:

new ChildData('tagtest', [], [], [new ChildData('tagtest', [], [], []),new ChildData('tagtest', [], [], []),new ChildData('tagtest', [], [], [])])

首次渲染出来是:

然后,点击按钮将数据更新成了:

new ChildData('tagtest', [], [], [new ChildData('tagtest', [], [], []),new ChildData('tagtest', [], [], []),new ChildData('tagtest', [], [], []), new ChildData('you', [], [], []),new ChildData('you', [], [], []),new ChildData('you', [], [], [])])

但是没有更新渲染:

在HarmonyOS中,@Observed@ObjectLink用于实现数据绑定,确保当数据发生变化时,UI能够自动更新。@Observed用于标记一个类,表示该类是可观察的,@ObjectLink用于标记一个属性,表示该属性与@Observed类的实例绑定。

ForEach是鸿蒙框架中用于动态生成UI组件的API,通常用于根据数据列表渲染多个UI元素。当@Observed@ObjectLink绑定的数据发生变化时,ForEach应该能够自动更新UI。

如果ForEach无法更新渲染,可能的原因包括:

  1. 数据未正确绑定:确保ForEach的输入数据源是@Observed类的实例,并且ForEach中的每个元素都正确使用了@ObjectLink进行绑定。

  2. 数据未触发更新:@Observed类的属性修改必须通过其setter方法进行,直接修改属性值不会触发UI更新。

  3. ForEach的key未正确设置:ForEach需要一个唯一的key来标识每个元素,如果key未正确设置或重复,可能导致UI无法正确更新。

  4. UI组件未正确实现:确保ForEach渲染的UI组件实现了@Component注解,并且能够响应数据变化。

  5. 异步更新问题:如果数据更新是在异步操作中进行的,可能需要使用@State@Prop来确保UI能够正确响应数据变化。

检查以上几点,确保数据绑定和UI渲染的逻辑正确,可以解决ForEach无法更新渲染的问题。

回到顶部