HarmonyOS鸿蒙Next中repeat渲染包含自定义组件的列表项并且开启virtualScroll渲染错乱

HarmonyOS鸿蒙Next中repeat渲染包含自定义组件的列表项并且开启virtualScroll渲染错乱 环境:DevEco Studio 5.0.5 Release

项目:

"targetSdkVersion": "5.0.5(17)",
"compatibleSdkVersion": "5.0.0(12)"

最近尝试使用List组件渲染支持虚拟滚动的列表,但是发现当列表项中使用自定义组件的话,列表无法正常渲染,比如我现在有100个子项,前面大概一半是正常的,但是后面的部分就会顺序错乱,这个是什么问题导致的呢? 不使用自定义组件,或者使用自定义组件但是不开启virtualScroll的情况不会有问题

感觉是组件复用出了问题,但又不知道该怎么修改,有大佬能帮忙看看吗

中部

cke_6176.png

底部

cke_13398.png

代码如下:

const arr: Array<number> = []

for (let i = 0; i < 100; i++) {
  arr.push(i)
}

@Entry
@Component
struct Index {
  @State currentIndex: number = 0

  build() {
    RelativeContainer() {
      List({space: 20}){
        Repeat<number>(arr).each(repeatItem => {
          // ListItem(){
          //   Text(repeatItem.item + '')
          // }
          ListItem(){
            CustomComp({message: 'item' + repeatItem.item})
          }.height(30)
        }).virtualScroll({
          totalCount: arr.length
        })
      }.divider({
        strokeWidth: 1,
        color: Color.Red
      }).alignListItem(ListItemAlign.Center)
    }
    .height('100%')
    .width('100%')
  }
}


@Component
struct CustomComp {
  @State message: string = ''
  aboutToAppear(): void {
    console.log('aboutToAppear', this.message)
  }

  aboutToDisappear(): void {
    console.log('aboutToDisappear', this.message)
  }


  aboutToRecycle(): void {
    console.log('aboutToRecycle', this.message)
  }

  onDidBuild(): void {
    console.log('onDidBuild', this.message)
  }

  build() {
    Text(this.message)
  }
}

更多关于HarmonyOS鸿蒙Next中repeat渲染包含自定义组件的列表项并且开启virtualScroll渲染错乱的实战教程也可以访问 https://www.itying.com/category-93-b0.html

3 回复

组件复用机制

小伙伴你好,Repeat组件采用动态复用机制,若自定义组件未正确声明依赖项(如@Link@ObjectLink@Prop变量),复用时可能保留旧数据,以下改为@Prop复现正常,望采纳。

const arr: Array<number> = []

for (let i = 0; i < 100; i++) {
  arr.push(i)
}

@Entry
@Component
struct Index {
  @State currentIndex: number = 0

  build() {
    RelativeContainer() {
      List({space: 20}){
        Repeat<number>(arr).each(repeatItem => {
          // ListItem(){
          //   Text(repeatItem.item + '')
          // }
          ListItem(){
            CustomComp({message: 'item' + repeatItem.item})
          }.height(30)
        }).virtualScroll({
          totalCount: arr.length
        })
      }.divider({
        strokeWidth: 1,
        color: Color.Red
      }).alignListItem(ListItemAlign.Center)
    }
    .height('100%')
    .width('100%')
  }
}


@Component
struct CustomComp {
  [@Prop](/user/Prop) message: string = ''
  aboutToAppear(): void {
    console.log('aboutToAppear', this.message)
  }

  aboutToDisappear(): void {
    console.log('aboutToDisappear', this.message)
  }


  aboutToRecycle(): void {
    console.log('aboutToRecycle', this.message)
  }

  onDidBuild(): void {
    console.log('onDidBuild', this.message)
  }

  build() {
    Text(this.message)
  }
}

更多关于HarmonyOS鸿蒙Next中repeat渲染包含自定义组件的列表项并且开启virtualScroll渲染错乱的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


在HarmonyOS Next中,使用repeat渲染包含自定义组件的列表项并开启virtualScroll时,可能出现渲染错乱问题。这是由于虚拟滚动机制与自定义组件布局计算存在兼容性问题。建议检查自定义组件的布局约束和尺寸计算逻辑,确保在虚拟滚动场景下能正确获取组件尺寸。可通过调整布局属性或使用固定尺寸来避免动态计算导致的渲染异常。

这是一个典型的虚拟滚动场景下组件复用机制导致的状态同步问题。当开启virtualScroll后,List组件会复用已创建的ListItem来优化性能,但自定义组件内部的状态管理可能无法正确同步。

问题核心在于:虚拟滚动复用组件时,自定义组件的生命周期回调(如aboutToAppear、aboutToRecycle)可能无法及时更新@State变量的值。从你的代码可以看到,CustomComp中的message状态在复用过程中没有正确重置。

建议解决方案:

  1. 使用@Prop替代@State:将CustomComp中的@State message改为@Prop,让父组件完全控制数据传递:
@Component
struct CustomComp {
  [@Prop](/user/Prop) message: string = ''
  // 移除[@State](/user/State)
}
  1. 确保key值唯一:为每个ListItem添加唯一key,帮助List组件正确识别和复用:
ListItem(){
  CustomComp({message: 'item' + repeatItem.item})
}.height(30).key(repeatItem.item.toString())
  1. 避免在自定义组件生命周期中依赖可能变化的状态,改为在build方法中直接使用传入的prop。

这种修改应该能解决虚拟滚动时的渲染错乱问题,因为@Prop提供了更明确的数据流控制,配合key值能让复用机制正常工作。

回到顶部