写点什么

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

作者:高心星
  • 2025-09-19
    江苏
  • 本文字数:2416 字

    阅读完需:约 8 分钟

鸿蒙应用开发——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 都渲染出来,耗费时间和内存。



日志输入结果:



// 父组件使用Repeat渲染列表@Entry@Componentstruct 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 个。



日志输出结果:



// 父组件使用Repeat渲染列表@Entry@Componentstruct 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 设置不同的显示模板。



// 父组件使用Repeat渲染列表@Entry@Componentstruct 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) //缓存两个节点 }}
复制代码


发布于: 刚刚阅读数: 3
用户头像

高心星

关注

天将降大任于斯人也,必先苦其心志。 2024-10-17 加入

华为开发者专家(HDE)。 10年教学经验,兼任多家科技公司技术顾问。先后从事JavaEE项目开发、Python爬虫、HarmonyOS移动应用开发等课程的教学工作。参与开发《鸿蒙应用开发基础》和《鸿蒙项目实战》等课程。

评论

发布
暂无评论
鸿蒙应用开发——Repeat组件的使用_缓存_高心星_InfoQ写作社区