鸿蒙应用开发——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) //缓存两个节点
  }
}
相关推荐
nashane4 小时前
HarmonyOS 6学习:CapsLock键失效诊断与长截图完整实现指南
学习·华为·harmonyos
richard_yuu6 小时前
鸿蒙心理测评模块实战|PHQ-9/GAD7双量表答题、实时计分与结果本地化存储
华为·harmonyos
不爱吃糖的程序媛9 小时前
2026年Electron 鸿蒙PC环境搭建指南
人工智能·华为·harmonyos
nashane9 小时前
HarmonyOS 6学习:长截图功能开发中的滚动拼接与权限处理实战
人工智能·华为·harmonyos
大师兄666810 小时前
从零开发一个 HarmonyOS 输入法——KikaInputMethod 完整拆解
harmonyos·服务卡片·harmonyos6·formkit
Python私教16 小时前
鸿蒙 NEXT 也能接 MCP?用 ArkTS 跑通 AI Agent 工具链
人工智能·华为·harmonyos
Swift社区18 小时前
分布式能力在鸿蒙 PC 上到底怎么用?
分布式·华为·harmonyos
nashane1 天前
HarmonyOS 6学习:外接键盘CapsLock与长截图功能的实战调试与完整解决方案
学习·华为·计算机外设·harmonyos
aqi001 天前
一文理清 HarmonyOS 6.0.2 涵盖的十个升级点
android·华为·harmonyos·鸿蒙·harmony