HarmonyOS鸿蒙Next中LazyForEach滑动到数据第一条的时候数据list没错,但是页面显示列如下标1的数据显示在了下标0
HarmonyOS鸿蒙Next中LazyForEach滑动到数据第一条的时候数据list没错,但是页面显示列如下标1的数据显示在了下标0
重现步骤为: 向下滑动加载后面的数据时
在滑动回到第一条 显示的数据错乱了
private datasource : CommonDataSource<CheckRecord> = new CommonDataSource()
Grid(){
LazyForEach(this.datasource,(item:CheckRecord,index:number) => {
GridItem() {
MyCard({item})
}.height(190).width("100%").borderRadius(10).backgroundColor("white")
},(item:CheckRecord) => item.exeConditionId)
}
@Reusable
@Component
struct MyCard {
@Prop item:CheckRecord
@Builder
iconHead(){
Text().height(12).width(4).backgroundColor("#0A59F7").margin({left:15,right:8})
}
@Builder
labelText(name: string,value?:string,suffix:string = ''){
Row() {
Text(name).fontSize(14).fontColor("#666666").padding({left:15})
Text(value ? value + suffix : '').layoutWeight(1).maxLines(1).textOverflow({overflow: TextOverflow.Ellipsis})
}.width("50%").height("20%")
}
build() {
Column(){
Row() {
this.iconHead()
Text(this.item.resBarnRoomName).fontSize(16).fontWeight(FontWeight.Bold).width('78%')
Text("查看").width('22%')
.padding({right:"10%"}).fontColor("#0088FE")
.fontSize(16)
.onClick((e:ClickEvent) => {
ZRouter.getInstance().setParam({
exeConditionId: this.item.exeConditionId,
resBarnRoomId: this.item.resBarnRoomId
}).navigation('fun/GranaryVisualizeGraph')
})
}.height("20%").width('100%').borderColor("#ebebeb").borderWidth({bottom:1})
Flex({wrap:FlexWrap.Wrap}){
Row(){
Text(`采集时间:`).fontSize(14).fontColor("#666666")
Text(`${this.item.dateCheck}`)
}.width("100%").height("18%").padding({left:15})
this.labelText("品名:", this.item.resPdtName)
this.labelText("最高温:",this.item.max?.toFixed(1),'℃')
this.labelText("最低温:", this.item.min?.toFixed(1),'℃')
this.labelText("平均温:",this.item.avg?.toFixed(1),'℃')
this.labelText("仓温:",this.item.temp?.toFixed(1),'℃')
this.labelText("仓湿:",this.item.hum?.toFixed(1),'%')
}
}.width("100%").height("100%")
}
}
更多关于HarmonyOS鸿蒙Next中LazyForEach滑动到数据第一条的时候数据list没错,但是页面显示列如下标1的数据显示在了下标0的实战教程也可以访问 https://www.itying.com/category-93-b0.html
class MyDataSource implements IDataSource {
private dataArray: string[] = []
private listener: DataChangeListener | undefined
public totalCount(): number {
return this.dataArray.length
}
public getData(index: number): string {
return this.dataArray[index]
}
public pushData(data: string): void {
this.dataArray.push(data)
}
public reloadListener(): void {
this.listener?.onDataReloaded()
}
public registerDataChangeListener(listener: DataChangeListener): void {
this.listener = listener
}
public unregisterDataChangeListener(listener: DataChangeListener): void {
this.listener = undefined
}
}
@Entry
@Component
struct ReusableLazyForEachCase {
private data: MyDataSource = new MyDataSource()
aboutToAppear() {
for (let i = 1; i < 100; i++) {
this.data.pushData(i + "")
}
}
build() {
Column() {
List() {
LazyForEach(this.data, (item: string) => {
ListItem() {
MyCard({ item })
}.height(190).width("100%").borderRadius(10).backgroundColor("white")
}, (item: string) => item)
}
.width('100%')
.height('100%')
.edgeEffect(EdgeEffect.Spring)
.scrollBar(BarState.On)
}
.width('100%')
.height('100%')
}
}
@Reusable
@Component
struct MyCard {
@Prop item: string = ''
@Builder
iconHead() {
Text().height(12).width(4).backgroundColor("#0A59F7").margin({ left: 15, right: 8 })
}
@Builder
labelText() {
Row() {
Text(this.item).fontSize(14).fontColor("#666666").padding({ left: 15 })
Text(this.item).layoutWeight(1).maxLines(1).textOverflow({ overflow: TextOverflow.Ellipsis })
}.width("50%").height("20%")
}
build() {
Column() {
Row() {
this.iconHead()
// Text(this.item.resBarnRoomName).fontSize(16).fontWeight(FontWeight.Bold).width('78%')
Text("查看").width('22%')
.padding({ right: "10%" }).fontColor("#0088FE")
.fontSize(16)
// .onClick((e:ClickEvent) => {
// // ZRouter.getInstance().setParam({
// // exeConditionId: this.item.exeConditionId,
// // resBarnRoomId: this.item.resBarnRoomId
// }).navigation('fun/GranaryVisualizeGraph')
// })
}.height("20%").width('100%').borderColor("#ebebeb").borderWidth({ bottom: 1 })
Flex({ wrap: FlexWrap.Wrap }) {
Row() {
Text(`采集时间:`).fontSize(14).fontColor("#666666")
Text(`${this.item}`)
}.width("100%").height("18%").padding({ left: 15 })
this.labelText()
this.labelText()
this.labelText()
this.labelText()
this.labelText()
this.labelText()
}
}.width("100%").height("100%")
}
}
用简易的数据,好像没有出现楼主的问题,建议查看打印一下id是否存在重复(keyGenerator 生成的键)标识组件
这个组件的简解我也写过:https://developer.huawei.com/consumer/cn/blog//topic/03197384103127220
更多关于HarmonyOS鸿蒙Next中LazyForEach滑动到数据第一条的时候数据list没错,但是页面显示列如下标1的数据显示在了下标0的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
可能为以下问题
- 键值生成器问题
LazyForEach的第三个参数要求生成 唯一且稳定 的键值。若item.exeConditionId存在重复或动态变化,会导致组件复用混乱。
强化键值唯一性
// 修改键生成逻辑,确保唯一性
LazyForEach(this.datasource, (item: CheckRecord, index: number) => {
// 使用稳定唯一键组合
GridItem() { /* ... */ }
}, (item: CheckRecord) => `${item.exeConditionId}_${index}`) // 添加索引提升唯一性
- 可复用组件数据同步问题
@Reusable装饰器可能导致组件复用后未及时更新@Prop属性,造成旧数据残留。
调整组件复用策略
// 去除[@Reusable](/user/Reusable)装饰器避免复用残留
@Component
struct MyCard {
[@Prop](/user/Prop) item: CheckRecord
// 原有构建逻辑...
}
- 数据更新机制不完整
数据源更新后未正确触发onDataReloaded或onDatasetChange方法,导致界面未及时刷新。
你检查一下 item.exeConditionId 是不是重复了。
- 键值生成器必须针对每个数据生成唯一的值,如果键值相同,将导致键值相同的UI组件渲染出现问题。
键值生成规则
在LazyForEach循环渲染过程中,系统为每个item生成一个唯一且持久的键值,用于标识对应的组件。键值变化时,ArkUI框架将视为该数组元素已被替换或修改,并基于新的键值创建新的组件。
LazyForEach提供了参数keyGenerator,开发者可以使用该函数生成自定义键值。如果未定义keyGenerator函数,ArkUI框架将使用默认的键值生成函数:(item: Object, index: number) => { return viewId + ‘-’ + index.toString(); }。viewId在编译器转换过程中生成,同一个LazyForEach组件内的viewId一致。
键值应满足以下条件。
- 键值具有唯一性,每个数据项对应的键值互不相同。
- 键值具有一致性,数据项不变时对应的键值也不变。
上述条件保证LazyForEach正确、高效地更新子组件,否则可能存在渲染结果异常、渲染效率降低等问题。
在HarmonyOS鸿蒙Next中,LazyForEach组件在滑动到第一条数据时出现显示错位,通常是由于组件复用机制导致的渲染状态未及时更新。可检查数据源与组件键值绑定是否唯一稳定,确保数据变更时触发正确的界面刷新。建议在数据项更新时调用刷新方法,并验证LazyForEach的组件生成逻辑与数据索引严格对应。
这个问题通常是由于LazyForEach在复用组件时,数据绑定没有正确更新导致的。从代码来看,你的MyCard组件使用了@Reusable装饰器,这会导致组件复用,但@Prop装饰的属性在复用时可能不会及时更新。
建议检查以下几点:
-
确保
exeConditionId作为key是唯一且稳定的。如果数据源变化时key不唯一,会导致组件复用混乱。 -
尝试将
@Prop改为@Link或@ObjectLink,确保数据变化时能正确触发UI更新:
@Link item: CheckRecord
-
如果问题仍然存在,可以暂时移除
@Reusable装饰器测试是否解决。 -
确认CommonDataSource的数据更新机制,确保数据变化时能正确通知到LazyForEach。
这种数据错乱问题在列表快速滚动时比较常见,主要原因是组件复用机制与数据更新不同步导致的。

