HarmonyOS 鸿蒙Next 为什么在用ForEach渲染Array<ResourceStr>时,只能渲染出来第一个图片呢?

发布于 1周前 作者 eggper 最后一次编辑是 5天前 来自 鸿蒙OS

HarmonyOS 鸿蒙Next 为什么在用ForEach渲染Array<ResourceStr>时,只能渲染出来第一个图片呢?

下面是本次测试的代码和演示结果。在渲染按钮组件的时候可以正常渲染,但是渲染图片的时候只能渲染出第一个。我看不懂keyGenerator的代码实现逻辑,不清楚为什么会这样qwq…求大佬帮帮忙,已经卡孩子三小时了。。。



@Entry
@Component
struct Parent {
  @State simpleList: Array<ResourceStr> = [$r("app.media.img_1"),$r("app.media.img_2"),$r("app.media.img_4")];
  build() {
    Row() {
      Column() {
        ForEach(this.simpleList, (item: string ) => {
            Image(item).size({height:30})
          Image(item).size({height:30})
          Image(item).size({height:30})
        }, (item: string) => item)
      }
      .width('100%')
      .height('100%')
    }
    .height('100%')
    .backgroundColor(0xF1F3F5)
  }
}
@Component
struct ChildItem {
  @Prop item: string;
  build() {
    Text(this.item)
      .fontSize(50)
  }
}


更多关于HarmonyOS 鸿蒙Next 为什么在用ForEach渲染Array<ResourceStr>时,只能渲染出来第一个图片呢?的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html

11 回复

你这种写法可以用日志打印出来看下

cke_1437.png

资源转string都是一样的

更多关于HarmonyOS 鸿蒙Next 为什么在用ForEach渲染Array<ResourceStr>时,只能渲染出来第一个图片呢?的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


非常感谢狼大佬,我总算找到困扰我的问题了。我最开始是想做一个ForEach嵌套,先用ForEach渲染一个类,然后再套一个ForEach渲染这个类里面的一个图片数组。。最开始我以为是嵌套循环的问题,我在网上试了很多方法,结果都不成功。所以我就试着分解一下问题,去用单层渲染做个测试,发现单层循环也只能渲染出来一个,我就想应该是这里出问题了。用大佬的方式,总算在单层的ForEach测试里面成功了。后面我又测试了一下simpleList:Array<Array<ResourStr>>,用ForEach的双重嵌套,用JSON.stringify(item)做key生成器的返回值,也成功了。这时候我已经排查出来不是双重ForEach嵌套的问题了。我回到我原来的项目,想要试试能不能成功,但还是失败了。我用大佬的方法打印了一下key生成器的JSON返回值。发现那个返回值是要遍历的数组所有元素的集合。。。简单来说,就是遍历一次一下子把我整个数组给拿走了。。真的很难理解这是为什么。明明是按照二层循环的格式写的。

为了方便大佬测试,代码就摘出来放到下面啦,可以直接复制到page页里面运行。。真的非常感谢【合十】【合十】【合十】

大佬!问题解决啦。。原来是在写数据的时候$r()少了一边括号,后面又莫名多了一个括号。编译器没报错,但把这些东西认为是一个整体了。。所以一直是重复主键


export class HomeRecommend{
  userAvatar:ResourceStr
  userName:string
  time:string

  titleName:string
  content:string
  contentImage:Array<ResourceStr>
  attachmentImage:ResourceStr
  attachmentName:string
  attachmentIcon:ResourceStr
  attachment:string
  repostIcon:ResourceStr
  repost:string
  commentIcon:ResourceStr
  commentCount:string
  likesIcon:ResourceStr
  likesCount:string
  recommend?:ResourceStr

  constructor(
    userAvatar:ResourceStr,
    userName:string,
    time:string,

    titleName:string,
    content:string,
    contentImage:Array<ResourceStr>,
    attachmentImage:ResourceStr,
    attachmentName:string,
    attachmentIcon:ResourceStr,
    attachment:string,
    repostIcon:ResourceStr,
    repost:string,
    commentIcon:ResourceStr,
    commentCount:string,
    likesIcon:ResourceStr,
    likesCount:string,
    recommend?:ResourceStr,

  ) {
    this.userAvatar=userAvatar
    this.userName=userName
    this.time=time
    this.titleName=titleName
    this.content=content
    this.contentImage=contentImage
    this.attachmentImage=attachmentImage
    this.attachmentName=attachmentName
    this.attachmentIcon=attachmentIcon
    this.attachment=attachment
    this.repostIcon=repostIcon
    this.repost=repost
    this.commentIcon=commentIcon
    this.commentCount=commentCount
    this.likesIcon=likesIcon
    this.likesCount=likesCount
    this.recommend=recommend
  }
}

export let homeRecomment:HomeRecommend[]=[
  new HomeRecommend($r('app.media.img_1'),"小通活动助手","01-06","学习通联动饿了么给大家送无门槛红包券啦!!","免费领取饿了么超级吃货卡\n点击下方链接将饿了么每天领红包设置为常用,这样就能每天都在学习通领取外卖红包啦\n饿了么每天领外卖红包...",[$r('app.media.img_2',$r('app.media.img_4'),$r('app.media.img_6'),$r('app.media.img_7'))],$r('app.media.img_5'),"免费领取饿了么超级会员吃货卡",$r('app.media.img_5'),"共2个附件",$r('app.media.img_6'),"转发",$r('app.media.activits'),"1.0万",$r('app.media.img_7'),"1.7万"),

]







@Entry
@Component
struct Page {
  @State message: string = 'Hello World';

  build() {
    Column(){
      ForEach(homeRecomment,(item:HomeRecommend)=>{
        ListItem(){
          Column(){
            Row(){
              Image(item.userAvatar).width("10%").margin({left:20,right:10}).borderWidth(1).borderColor("#bfbfbf")
              Column(){
                Text(item.userName).fontSize(16)
                Text(item.time).fontSize(10).fontColor("#bfbfbf").margin({top:1})
              }.alignItems(HorizontalAlign.Start)
            }.width('100%').margin({top:20}).justifyContent(FlexAlign.Start)
            Text(item.titleName).width("90%").maxLines(2).fontSize(20).fontWeight(FontWeight.Bold).margin({top:5})
            Text(item.content).width("90%").maxLines(5).fontSize(16).fontColor("#4f4f4f").margin({top:10})
            Flex(){
              ForEach(item.contentImage,(item:ResourceStr)=>{
                Column(){
                  Image(item).width(100)
                }.width('20%')
              },(newitem:string)=>{
                let flag=0
                flag++
                console.log("JSON-newitem:"+JSON.stringify(newitem));
                console.log("flag:"+flag.toString());

                // return JSON.stringify(item)
                return flag.toString()
              })
            }.width("100%")
            Row(){
              Image(item.attachmentImage).width(50).height(50).padding(10)
              Text(item.attachmentName).fontSize(10).padding(8).margin({left:-5}).fontColor(Color.Black)
            }.width("95%").backgroundColor("#dadada").borderRadius(5).margin({top:5,bottom:5})
            Row(){
              Row(){
                Image(item.attachmentIcon).width(10)
                Text(item.attachment).fontSize(10).fontColor("#bfbfbf")
              }.width("95%").justifyContent(FlexAlign.End)
            }.width("100%")
            Row(){
              Row(){
                Image(item.repostIcon).width(16).margin({right:5})
                Text(item.repost).fontSize(11)
              }.padding(10).width("30%").justifyContent(FlexAlign.Center)
              Row(){
                Image(item.commentIcon).width(16).margin({right:5})
                Text(item.commentCount).fontSize(11)
              }.padding(10).width("30%").justifyContent(FlexAlign.Center)
              Row(){
                Image(item.likesIcon).width(16).margin({right:5})
                Text(item.likesCount).fontSize(11)
              }.padding(10).width("30%").justifyContent(FlexAlign.Center)
            }.justifyContent(FlexAlign.SpaceBetween).width("100%")
          }.alignItems(HorizontalAlign.Center).width("100%")
        }.width("100%")

      })
    }
  }
}

你这两个ForEach写法都有问题,第一个Foreach因为没有写keyGenerator,所以用的是默认的那套生成规则,虽然暂时没问题,但不清楚你后续业务会不会去动态变化数据,最好是给一个业务上的唯一主键。第二个ForEach我看你里面用的是flag作为主键返回,你这个flag是一个局部变量吧,每次生成的都会是1

嗯嗯,我是不懂 这个逻辑,以为key生成器会在item迭代器遍历数组的时候,遍历到一个元素就会运行一次。我昨晚JSON.stringify()的返回值都是一样的,就在想自己能不能用C语言里面用类似for循环的方法,弄个自增的i来遍历整个数组。。。结果失败了,hhh。现在问题解决啦,今天早上发现是自己的资源写入的时候出了问题。一个资源少写了右括号,然后在整个数组最后面多了一个括号。导致数组里面只有一个内容。编译器不报错。。。

不是唯一主键

HarmonyOS 鸿蒙Next 在使用 ForEach 渲染 Array<ResourceStr> 时只能渲染出第一个图片的问题,通常与资源加载或视图更新机制有关。

ForEach 组件用于遍历数组并生成相应的子组件。若只能渲染第一个图片,可能的原因包括:

  1. 资源路径问题:确保 Array<ResourceStr> 中的每个元素都指向有效的资源路径。资源路径错误或缺失可能导致资源加载失败。

  2. 资源加载异步性:资源加载可能是异步的,如果未正确处理异步加载状态,可能导致只有第一个资源加载完成并显示。

  3. 视图更新:在数组内容发生变化后,确保视图已正确触发更新。视图更新未触发或延迟可能导致显示内容不正确。

  4. 组件复用问题ForEach 生成的子组件在视图复用过程中可能出现状态混乱,导致只有第一个组件正确显示。

检查这些方面,确保资源路径正确、异步加载处理得当、视图更新及时,以及组件状态管理正确。

如果问题依旧没法解决请联系官网客服,官网地址是:https://www.itying.com/category-93-b0.html

回到顶部