HarmonyOS 解析Json数据添加到数据源不刷新UI

@Entry  
@Component  
struct DishSearchPage {  
  @State articleList: Array<Article> = []  
  res = `{"code":0,"data":[{"id":"001","title":"第0篇文章","brief":"文章简介内容","isLiked":false,"likesCount":100},{"id":"002","title":"第1篇文章","brief":"文章简介内容","isLiked":false,"likesCount":100},{"id":"003","title":"第2篇文章","brief":"文章简介内容","isLiked":false,"likesCount":100},{"id":"004","title":"第4篇文章","brief":"文章简介内容","isLiked":false,"likesCount":100},{"id":"005","title":"第5篇文章","brief":"文章简介内容","isLiked":false,"likesCount":100},{"id":"006","title":"第6篇文章","brief":"文章简介内容","isLiked":false,"likesCount":100}]}`;  
  aboutToAppear(): void {  
    let articleRes: ArticleRes = JSON.parse(this.res)  
    articleRes?.data?.forEach((v) => {  
  
      // this.articleList.push(JSON.parse(JSON.stringify(v)))  
  
      this.articleList.push(JSON.parse(JSON.stringify(v)))  
    })  
  }  
  
  build() {  
    List() {  
      ForEach(this.articleList, (item: Article) => {  
        ListItem() {  
          ArticleCard({  
            article: item  
          })  
            .margin({ top: 20 })  
        }  
      }, (item: Article) => item.id)  
    }  
    .padding(20)  
    .scrollBar(BarState.Off)  
    .backgroundColor(0xF1F3F5)  
  }  
}  
  
@Component  
struct ArticleCard {  
  @ObjectLink article: Article;  
  
  handleLiked() {  
    this.article.isLiked = !this.article.isLiked;  
    this.article.likesCount = this.article.isLiked ? this.article.likesCount + 1 : this.article.likesCount - 1;  
  }  
  
  build() {  
    Row() {  
      Image($r('app.media.icon'))  
        .width(80)  
        .height(80)  
        .margin({ right: 20 })  
  
      Column() {  
        Text(this.article.title)  
          .fontSize(20)  
          .margin({ bottom: 8 })  
        Text(this.article.brief)  
          .fontSize(16)  
          .fontColor(Color.Gray)  
          .margin({ bottom: 8 })  
  
        Row() {  
          Text(this.article.likesCount.toString())  
            .fontSize(16)  
        }  
        .justifyContent(FlexAlign.Center)  
      }  
      .alignItems(HorizontalAlign.Start)  
      .width('80%')  
      .height('100%')  
    }  
    .padding(20)  
    .borderRadius(12)  
    .height(120)  
    .width('100%')  
    .justifyContent(FlexAlign.SpaceBetween)  
    .backgroundColor(this.article.isLiked ? Color.Blue : '#FFECECEC')  
    .onClick(() => this.handleLiked())  
  }  
}  
  
@Observed  
class ArticleRes {  
  code: number = -1  
  data: Array<Article> = []  
}  
  
@Observed  
class Article {  
  id: string;  
  title: string;  
  brief: string;  
  isLiked: boolean;  
  likesCount: number;  
  
  constructor(id: string, title: string, brief: string, isLiked: boolean, likesCount: number) {  
    this.id = id;  
    this.title = title;  
    this.brief = brief;  
    this.isLiked = isLiked;  
    this.likesCount = likesCount;  
  }  
}

let articleRes: ArticleRes = JSON.parse(this.res)

articleRes?.data?.forEach((v) => this.articleList.push(v))

解析Json数据 然后添加到列表的List就不行。

[  
  new Article('001', '第0篇文章', '文章简介内容', false, 100),  
  new Article('002', '第1篇文章', '文章简介内容', false, 100)  
].forEach((v) => {  
  this.articleList.push(v)  
})

new的就可以 为什么呢?

场景就是这样的 接口返了一个类似ArticleRes的json数据 想问下要怎么操作才能让数据源数组项子属性变化 ui跟着变化呢?

这种要怎么刷新呢?

HarmonyOS
2024-09-26 10:55:44
浏览
收藏 0
回答 2
待解决
回答 2
按赞同
/
按时间
鱼弦CTO
1

在HarmonyOS的ArkUI中,​​@State​​​ 和 ​​@Observed​​ 数据的变化会自动触发UI更新。但是你遇到的问题是,当从JSON解析并添加到数组后,UI没有及时刷新。这通常与对象的引用和响应式系统有关。

### 原因分析

当你直接从JSON解析数据并添加到 ​​@State​​ 的数组中时,这些新对象可能没有被正确地观察到,因此无法触发UI更新。相比之下,通过 ​​new​​ 关键字创建的对象因为是在受控环境下生成的,所以能够被正确地观察到。

## 解决方案

可以通过显式构造新的 ​​Article​​ 对象来确保这些对象被正确观察到。以下是优化后的代码示例:

### 父组件代码

// MainPage.ets
import { CommonDataSource } from './CommonDataSource';
import { ArticleCard } from './ArticleCard';

@Entry
@Component
struct DishSearchPage {
    @State articleList: Array<Article> = [];
    private res: string = `{"code":0,"data":[{"id":"001","title":"第0篇文章","brief":"文章简介内容","isLiked":false,"likesCount":100},{"id":"002","title":"第1篇文章","brief":"文章简介内容","isLiked":false,"likesCount":100},{"id":"003","title":"第2篇文章","brief":"文章简介内容","isLiked":false,"likesCount":100},{"id":"004","title":"第4篇文章","brief":"文章简介内容","isLiked":false,"likesCount":100},{"id":"005","title":"第5篇文章","brief":"文章简介内容","isLiked":false,"likesCount":100},{"id":"006","title":"第6篇文章","brief":"文章简介内容","isLiked":false,"likesCount":100}]}`;

    aboutToAppear(): void {
        let articleRes: ArticleRes = JSON.parse(this.res);
        articleRes?.data?.forEach((v) => {
            // 使用构造函数创建新的 Article 实例
            let newArticle = new Article(v.id, v.title, v.brief, v.isLiked, v.likesCount);
            this.articleList.push(newArticle);
        });
    }

    build() {
        List() {
            ForEach(this.articleList, (item: Article) => {
                ListItem() {
                    ArticleCard({
                        article: item
                    }).margin({ top: 20 });
                }
            }, (item: Article) => item.id)
        }
        .padding(20)
        .scrollBar(BarState.Off)
        .backgroundColor(0xF1F3F5);
    }
}

### 子组件代码

// ArticleCard.ets
@Component
struct ArticleCard {
    @ObjectLink article: Article;

    handleLiked() {
        this.article.isLiked = !this.article.isLiked;
        this.article.likesCount = this.article.isLiked ? this.article.likesCount + 1 : this.article.likesCount - 1;
    }

    build() {
        Row() {
            Image($r('app.media.icon'))
                .width(80)
                .height(80)
                .margin({ right: 20 });

            Column() {
                Text(this.article.title)
                    .fontSize(20)
                    .margin({ bottom: 8 });

                Text(this.article.brief)
                    .fontSize(16)
                    .fontColor(Color.Gray)
                    .margin({ bottom: 8 });

                Row() {
                    Text(this.article.likesCount.toString())
                        .fontSize(16);
                }
                .justifyContent(FlexAlign.Center);
            }
            .alignItems(HorizontalAlign.Start)
            .width('80%')
            .height('100%');
        }
        .padding(20)
        .borderRadius(12)
        .height(120)
        .width('100%')
        .justifyContent(FlexAlign.SpaceBetween)
        .backgroundColor(this.article.isLiked ? Color.Blue : '#FFECECEC')
        .onClick(() => this.handleLiked());
    }
}

### 数据模型

@Observed
class ArticleRes {
    code: number = -1;
    data: Array<Article> = [];
}

@Observed
class Article {
    id: string;
    title: string;
    brief: string;
    isLiked: boolean;
    likesCount: number;

    constructor(id: string, title: string, brief: string, isLiked: boolean, likesCount: number) {
        this.id = id;
        this.title = title;
        this.brief = brief;
        this.isLiked = isLiked;
        this.likesCount = likesCount;
    }
}

### 总结

通过调用 ​​Article​​ 构造函数创建新的 ​​Article​​ 实例,可以确保这些实例被正确观察到,从而触发UI更新。当你直接从JSON解析并赋值时,由于这些对象没有通过 ​​Observed​​ 相关机制生成,可能不会触发UI更新。因此,使用显式构造的新对象可以解决这个问题。

分享
微博
QQ
微信
回复
2024-09-26 18:59:11
zbw_apple

使用三方库 class-transformer:https://ohpm.openharmony.cn/#/cn/detail/class-transformer

Json转Class 就行了。

分享
微博
QQ
微信
回复
2024-09-26 17:48:10
相关问题
HarmonyOS 卡片添加到负一屏
464浏览 • 1回复 待解决
lazyforeach替换数据源解决方案
740浏览 • 1回复 待解决
HarmonyOS picker选择器的数据源问题
4浏览 • 1回复 待解决
修改ForEach使用的数据对象,UI刷新
1875浏览 • 1回复 待解决
HarmonyOS使用@ObjectLink 数据刷新
800浏览 • 2回复 待解决