鸿蒙6.0应用开发——Repeat组件的高效列表渲染
核心机制与使用规范
Repeat组件用于基于数组数据实现循环渲染,仅可在支持滚动懒加载的容器中使用,如List、Grid、Swiper、WaterFlow及ListItemGroup。它通过动态管理子组件的创建与销毁,依据当前可视区域与预加载范围(可自定义)按需渲染内容,显著提升性能。
- 必须配合滚动容器使用,且每个滚动容器内仅允许存在一个Repeat实例。
- 子组件必须为容器支持的类型(如List中使用ListItem)。
- 不兼容V1装饰器,混用将导致渲染异常。
- 暂不支持动画效果。
- 当与自定义组件或@Builder函数结合时,需整体传递RepeatItem数据,以确保响应式更新。
结构定义
Repeat的子组件由两个关键属性定义:
.each():定义默认模板,用于所有项的通用渲染。.template():定义可复用的特定模板,通过.templateId()动态绑定。
首次渲染时,Repeat根据有效加载范围创建节点,支持通过cachedCount(n)设置预加载缓存数量,默认为1。
典型应用场景
全量渲染示例(低效)
直接渲染全部100项,初始阶段即创建全部组件,消耗大量内存与渲染时间。
@Entry
@Component
struct RepeatDemo {
@State data: string[] = [];
aboutToAppear() {
for (let i = 0; i < 100; i++) {
this.data.push(`条目 ${i}`);
}
}
build() {
List() {
Repeat(this.data)
.each((item: RepeatItem<string>) => {
ListItem() {
Text(item.item)
.fontSize(20)
.width('100%')
.textAlign(TextAlign.Center)
}.onAppear(() => {
console.log('渲染:', item.item);
})
})
}
.width('100%')
}
}
启用懒加载与缓存优化
开启虚拟滚动并设置缓存数,仅在可视范围内渲染,滑动时重用已缓存节点,极大降低资源开销。
List() {
Repeat(this.data)
.each((item: RepeatItem<string>) => {
ListItem() {
Text(item.item)
.fontSize(20)
.width('100%')
.textAlign(TextAlign.Center)
}.onAppear(() => {
console.log('出现:', item.item);
})
})
.virtualScroll() // 启用懒加载
.cachedCount(2) // 缓存2个额外节点
}
.width('100%')
多模板动态切换
根据索引条件动态选择不同显示样式,适用于需要差异化展示的列表场景。
List() {
Repeat(this.data)
.each((item: RepeatItem<string>) => {
ListItem() {
Text(item.item)
.fontSize(20)
.width('100%')
.textAlign(TextAlign.Center)
}.onAppear(() => {
console.log('渲染:', item.item);
})
})
.template('yellow', (item: RepeatItem<string>) => {
ListItem() {
Text(item.item)
.fontSize(20)
.width('100%')
.textAlign(TextAlign.Center)
.backgroundColor(Color.Yellow)
}.onAppear(() => {
console.log('黄色模板渲染:', item.item);
})
})
.template('red', (item: RepeatItem<string>) => {
ListItem() {
Text(item.item)
.fontSize(20)
.width('100%')
.textAlign(TextAlign.Center)
.backgroundColor(Color.Red)
}.onAppear(() => {
console.log('红色模板渲染:', item.item);
})
})
.templateId((_, index) => {
return index % 3 === 1 ? 'yellow' : index % 3 === 2 ? 'red' : '';
})
.virtualScroll()
.cachedCount(2)
}
.width('100%')