鸿蒙应用开发——Repeat组件的使用

【高心星出品】

Repeat组件的使用

概念

Repeat基于数组类型数据来进行循环渲染,一般与容器组件配合使用。

Repeat根据容器组件的有效加载范围(屏幕可视区域+预加载区域)加载子组件。当容器滑动/数组改变时,Repeat会根据父容器组件的布局过程重新计算有效加载范围,并管理列表子组件节点的创建与销毁。

  • Repeat必须在滚动类容器组件内使用,仅有List、ListItemGroup、Grid、Swiper以及WaterFlow组件支持Repeat懒加载场景。

    循环渲染只允许创建一个子组件,子组件应当是允许包含在容器组件中的子组件。例如:Repeat与List组件配合使用时,子组件必须为ListItem组件。

  • Repeat不支持V1装饰器,混用V1装饰器会导致渲染异常。

  • Repeat当前不支持动画效果。

  • 滚动容器组件内只能包含一个Repeat。以List为例,不建议同时包含ListItem、ForEach、LazyForEach,不建议同时包含多个Repeat。

  • 当Repeat与自定义组件或@Builder函数混用时,必须将RepeatItem类型整体进行传参,组件才能监听到数据变化。详见Repeat与@Builder混用。

Repeat子组件由.each()和.template()属性定义,只允许包含一个子组件。当页面首次渲染时,Repeat根据当前的有效加载范围(屏幕可视区域+预加载区域)按需创建子组件。如下图所示:

repeat默认会分配1个预加载节点,通过cachecount可以认为调整预加载节点个数。

案例

repeat全量加载数组案例:

下面案例使用list加载全量数组元素,第一运行的时候就会把100个listitem都渲染出来,耗费时间和内存。

日志输入结果:

scss 复制代码
// 父组件使用Repeat渲染列表
@Entry
@Component
struct repeatpage {
  @State items: string[] = [];
  aboutToAppear() {
    // 初始化数据
    for (let i = 0; i < 100; i++) {
      this.items.push(`列表项 ${i}`);
    }
  }
​
  build() {
    List() {
      Repeat(this.items)
        // 遍历每个数组元素
        .each((item: RepeatItem<string>) => {
          ListItem() {
           Text(item.item)
             .fontSize(20)
             .width('100%')
             .textAlign(TextAlign.Center)
          }.onAppear(()=>{
            // 当listitem渲染的时候调用
            console.log('gxxt ',item.item+' 出现了')
          })
        })
    }
    .width('100%')
  }
}
repeat开启懒加载和设置预加载数量

下面案例开启了virtualScroll懒加载和cachedCount预加载数量,可以看到第一次只渲染了可见区域的listitem,随着滑动重用预加载的节点。第一次渲染了30的listem,缓存了两个节点,所以加载的数据为32个。

日志输出结果:

scss 复制代码
// 父组件使用Repeat渲染列表
@Entry
@Component
struct repeatpage {
  @State items: string[] = [];
  aboutToAppear() {
    // 初始化数据
    for (let i = 0; i < 100; i++) {
      this.items.push(`列表项 ${i}`);
    }
  }
​
  build() {
    List() {
      Repeat(this.items)
        // 遍历每个数组元素
        .each((item: RepeatItem<string>) => {
          ListItem() {
           Text(item.item)
             .fontSize(20)
             .width('100%')
             .textAlign(TextAlign.Center)
          }.onAppear(()=>{
            // 当listitem渲染的时候调用
            console.log('gxxt ',item.item+' 出现了')
          })
        })// 开启懒加载
        .virtualScroll()
    }
    .width('100%')
    .cachedCount(2) //缓存两个节点
  }
}
repeat设置加载模板

下面案例中给repeat设置通用模板和huang模板和hong模板,根据index设置不同的显示模板。

scss 复制代码
// 父组件使用Repeat渲染列表
@Entry
@Component
struct repeatpage {
  @State items: string[] = [];
​
  aboutToAppear() {
    // 初始化数据
    for (let i = 0; i < 100; i++) {
      this.items.push(`列表项 ${i}`);
    }
  }
​
  build() {
    List() {
      Repeat(this.items)// 遍历每个数组元素
        .each((item: RepeatItem<string>) => {
          ListItem() {
            Text(item.item)
              .fontSize(20)
              .width('100%')
              .textAlign(TextAlign.Center)
          }.onAppear(() => {
            // 当listitem渲染的时候调用
            console.log('gxxt ', item.item + ' 出现了')
          })
        })
        .template('huang', (item: RepeatItem<string>) => {
          ListItem() {
            Text(item.item)
              .fontSize(20)
              .width('100%')
              .textAlign(TextAlign.Center)
              .backgroundColor(Color.Yellow)
          }.onAppear(() => {
            // 当listitem渲染的时候调用
            console.log('gxxt ', item.item + ' 出现了')
          })
        })
        .template('hong', (item: RepeatItem<string>) => {
          ListItem() {
            Text(item.item)
              .fontSize(20)
              .width('100%')
              .textAlign(TextAlign.Center)
              .backgroundColor(Color.Red)
          }.onAppear(() => {
            // 当listitem渲染的时候调用
            console.log('gxxt ', item.item + ' 出现了')
          })
        })
        .templateId((item: string, index: number) => {
          // 下标被3除余1 加载huang模板  被3除余2 加载hong模板 其他的加载each的通用模板
          if (index % 3 == 1) {
            return 'huang'
          } else if (index % 3 == 2) {
            return 'hong'
          } else {
            return ''
          }
        })// 开启懒加载
        .virtualScroll()
    }
    .width('100%')
    .cachedCount(2) //缓存两个节点
  }
}
相关推荐
爱笑的眼睛1116 分钟前
HarmonyOS SaveButton深度解析:安全便捷的媒体资源保存方案
安全·华为·harmonyos·媒体
无风听海2 小时前
HarmonyOS之Emitter
harmonyos
光芒Shine6 小时前
【ArkTS-通用事件】
harmonyos
Jackson_Li8 小时前
鸿蒙 Tab 中的 WebView 如何优雅地拦截侧滑返回?
harmonyos
0xCode 小新8 小时前
【鸿蒙心迹】参加ICT大赛对我的影响和帮助
harmonyos
程序员潘Sir9 小时前
鸿蒙应用开发从入门到实战(十八):组件编程思想之代码复用
harmonyos·鸿蒙
安卓开发者1 天前
鸿蒙NEXT跨设备通信:掌握URPC,实现远程程序调用
华为·harmonyos
程序员潘Sir1 天前
鸿蒙应用开发从入门到实战(十七):ArkUI组件List&列表布局
harmonyos·鸿蒙