HarmonyOS 鸿蒙Next 为什么在用ForEach渲染Array<ResourceStr>时,只能渲染出来第一个图片呢?
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
你这种写法可以用日志打印出来看下
资源转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
组件用于遍历数组并生成相应的子组件。若只能渲染第一个图片,可能的原因包括:
-
资源路径问题:确保
Array<ResourceStr>
中的每个元素都指向有效的资源路径。资源路径错误或缺失可能导致资源加载失败。 -
资源加载异步性:资源加载可能是异步的,如果未正确处理异步加载状态,可能导致只有第一个资源加载完成并显示。
-
视图更新:在数组内容发生变化后,确保视图已正确触发更新。视图更新未触发或延迟可能导致显示内容不正确。
-
组件复用问题:
ForEach
生成的子组件在视图复用过程中可能出现状态混乱,导致只有第一个组件正确显示。
检查这些方面,确保资源路径正确、异步加载处理得当、视图更新及时,以及组件状态管理正确。
如果问题依旧没法解决请联系官网客服,官网地址是:https://www.itying.com/category-93-b0.html