【高心星出品】
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
@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 个。
日志输出结果:
// 父组件使用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 设置不同的显示模板。
// 父组件使用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) //缓存两个节点
}
}
复制代码
评论