1# Repeat 2<!--Kit: ArkUI--> 3<!--Subsystem: ArkUI--> 4<!--Owner: @liubihao--> 5<!--Designer: @keerecles--> 6<!--Tester: @TerryTsao--> 7<!--Adviser: @HelloCrease--> 8 9> **说明:** 10> 11> 本模块首批接口从API version 12开始支持。后续版本的新增接口,采用上角标单独标记接口的起始版本。 12 13Repeat基于数组类型数据来进行循环渲染,一般与容器组件配合使用。 14 15本文档仅为API参数说明。组件描述和使用说明见[Repeat开发者指南](../../../ui/state-management/arkts-new-rendering-control-repeat.md)。 16 17## 接口 18 19### Repeat: \<T\>(arr: Array\<T\>) 20 21**卡片能力:** 从API version 12开始,该接口支持在ArkTS卡片中使用。 22 23**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 24 25**系统能力:** SystemCapability.ArkUI.ArkUI.Full 26 27**参数:** 28 29| 参数名 | 类型 | 必填 | 说明 | 30| ------ | ---------- | -------- | -------- | 31| arr | Array\<T\> | 是 | 数据源,为`Array<T>`类型的数组,由开发者决定数据类型。 | 32 33**示例:** 34```ts 35// arr是Array<string>类型的数组,以arr为数据源创建Repeat组件 36Repeat<string>(this.arr) 37``` 38 39### Repeat: \<T\>(arr: RepeatArray\<T\>)<sup>18+</sup> 40 41> **说明:** 42> 43> 从API version 18开始,Repeat数据源支持RepeatArray类型。 44 45**卡片能力:** 从API version 18开始,该接口支持在ArkTS卡片中使用。 46 47**原子化服务API:** 从API version 18开始,该接口支持在原子化服务中使用。 48 49**系统能力:** SystemCapability.ArkUI.ArkUI.Full 50 51**参数:** 52 53| 参数名 | 类型 | 必填 | 说明 | 54| ------ | ---------- | -------- | -------- | 55| arr | [RepeatArray\<T\>](#repeatarrayt18) | 是 | 数据源,为`RepeatArray<T>`类型的数组,由开发者决定数据类型。 | 56 57## 属性 58 59**卡片能力:** 从API version 12开始,该接口支持在ArkTS卡片中使用。 60 61**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 62 63**系统能力:** SystemCapability.ArkUI.ArkUI.Full 64 65### each 66 67each(itemGenerator: (repeatItem: RepeatItem\<T\>) => void) 68 69组件生成函数。当所有`.template()`的type和`.templateId()`返回值不匹配时,将使用`.each()`处理数据项。 70 71> **说明** 72> 73> `each`属性必须有,否则运行时会报错。 74> `itemGenerator`的参数为`RepeatItem`,该参数将`item`和`index`结合到了一起,请勿将`RepeatItem`参数拆开使用。 75 76**卡片能力:** 从API version 12开始,该接口支持在ArkTS卡片中使用。 77 78**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 79 80**系统能力:** SystemCapability.ArkUI.ArkUI.Full 81 82**参数:** 83 84| 参数名 | 类型 | 必填 | 说明 | 85| ------ | ---------- | -------- | -------- | 86| repeatItem | [RepeatItem](#repeatitemt)\<T\> | 否 | repeat数据项。 | 87 88**示例:** 89```ts 90// arr是Array<string>类型的数组,为每个数据创建一个Text组件 91Repeat<string>(this.arr) 92 .each((obj: RepeatItem<string>) => { Text(obj.item) }) 93``` 94 95### key 96 97key(keyGenerator: (item: T, index: number) => string) 98 99键值生成函数。 100 101**卡片能力:** 从API version 12开始,该接口支持在ArkTS卡片中使用。 102 103**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 104 105**系统能力:** SystemCapability.ArkUI.ArkUI.Full 106 107**参数:** 108 109| 参数名 | 类型 | 必填 | 说明 | 110| ------ | ---------- | -------- | -------- | 111| item | T | 否 | `arr`数组中的数据项。 | 112| index | number | 否 | `arr`数组中的数据项索引。 | 113 114**示例:** 115```ts 116// arr是Array<string>类型的数组,为每个数据创建一个Text组件 117// 并将字符串的值作为其键值 118Repeat<string>(this.arr) 119 .each((obj: RepeatItem<string>) => { Text(obj.item) }) 120 .key((obj: string) => obj) 121``` 122 123### virtualScroll 124 125virtualScroll(virtualScrollOptions?: VirtualScrollOptions) 126 127`Repeat`开启虚拟滚动。 128 129**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 130 131**系统能力:** SystemCapability.ArkUI.ArkUI.Full 132 133**参数:** 134 135| 参数名 | 类型 | 必填 | 说明 | 136| ------ | ---------- | -------- | -------- | 137| virtualScrollOptions | [VirtualScrollOptions](#virtualscrolloptions) | 否 | 虚拟滚动配置项。 | 138 139**示例:** 140```ts 141// arr是Array<string>类型的数组,为每个数据创建一个Text组件 142// 在List容器组件中使用Repeat,并打开virtualScroll 143List() { 144 Repeat<string>(this.arr) 145 .each((obj: RepeatItem<string>) => { ListItem() { Text(obj.item) }}) 146 .virtualScroll() 147} 148``` 149 150### template 151 152template(type: string, itemBuilder: RepeatItemBuilder\<T\>, templateOptions?: TemplateOptions) 153 154由template type渲染对应的template子组件。 155 156**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 157 158**系统能力:** SystemCapability.ArkUI.ArkUI.Full 159 160**参数:** 161 162| 参数名 | 类型 | 必填 | 说明 | 163| ------ | ---------- | -------- | -------- | 164| type | string | 是 | 当前模板类型。 | 165| itemBuilder | [RepeatItemBuilder](#repeatitembuildert)\<T\> | 是 | 组件生成函数。 | 166| templateOptions | [TemplateOptions](#templateoptions对象说明) | 否 | 当前模板配置项。 | 167 168**示例:** 169```ts 170// arr是Array<string>类型的数组 171// 在List容器组件中使用Repeat,并打开virtualScroll 172// 创建模板temp,该模板为数据创建Text组件 173List() { 174 Repeat<string>(this.arr) 175 .each((obj: RepeatItem<string>) => {}) 176 .virtualScroll() 177 .template('temp', (obj: RepeatItem<string>) => { ListItem() { Text(obj.item) }}) 178} 179``` 180 181### templateId 182 183templateId(typedFunc: TemplateTypedFunc\<T\>) 184 185为当前数据项分配template type。 186 187**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 188 189**系统能力:** SystemCapability.ArkUI.ArkUI.Full 190 191**参数:** 192 193| 参数名 | 类型 | 必填 | 说明 | 194| ------ | ---------- | -------- | -------- | 195| typedFunc | [TemplateTypedFunc](#templatetypedfunct)\<T\> | 是 | 生成当前数据项对应的template type。 | 196 197**示例:** 198```ts 199// arr是Array<string>类型的数组 200// 在List容器组件中使用Repeat,并打开virtualScroll 201// 创建模板temp,该模板为数据创建Text组件 202// 所有数据项都使用temp模板 203List() { 204 Repeat<string>(this.arr) 205 .each((obj: RepeatItem<string>) => {}) 206 .virtualScroll() 207 .template('temp', (obj: RepeatItem<string>) => { ListItem() { Text(obj.item) }}) 208 .templateId((item: string, index: number) => { return 'temp' }) 209} 210``` 211 212## RepeatArray\<T\><sup>18+</sup> 213 214type RepeatArray\<T\> = Array\<T\> | ReadonlyArray\<T\> | Readonly\<Array\<T\>\> 215 216Repeat数据源参数联合类型。 217 218**卡片能力:** 从API version 18开始,该接口支持在ArkTS卡片中使用。 219 220**原子化服务API:** 从API version 18开始,该接口支持在原子化服务中使用。 221 222**系统能力:** SystemCapability.ArkUI.ArkUI.Full 223 224| 类型 | 说明 | 225| -------- | -------- | 226| Array\<T\> | 常规数组类型。 | 227| ReadonlyArray\<T\> | 只读数组类型,不允许数组对象变更。 | 228| Readonly\<Array\<T\>> | 只读数组类型,不允许数组对象变更。 | 229 230## RepeatItem\<T\> 231 232**卡片能力:** 从API version 12开始,该接口支持在ArkTS卡片中使用。 233 234**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 235 236**系统能力:** SystemCapability.ArkUI.ArkUI.Full 237 238| 名称 | 类型 | 必填 | 说明 | 239| ------ | ------ | ---- | -------------------------------------------- | 240| item | T | 是 | arr中每一个数据项。T为开发者传入的数据类型。 | 241| index | number | 是 | 当前数据项对应的索引。 | 242 243## VirtualScrollOptions 244 245**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 246 247**系统能力:** SystemCapability.ArkUI.ArkUI.Full 248 249| 名称 | 类型 | 必填 | 说明 | 250| ---------- | ------ | ---- | ------------------------------------------------------------ | 251| totalCount | number | 否 | 加载的数据项总数,可以不等于数据源长度。<br>取值范围:[0, +∞)<br>**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 | 252| reusable<sup>18+</sup> | boolean | 否 | 是否开启复用功能。true代表开启复用,false代表关闭复用。<br>默认值:true<br>**原子化服务API:** 从API version 18开始,该接口支持在原子化服务中使用。 | 253| onLazyLoading<sup>19+</sup> | (index: number) => void | 否 | 数据懒加载函数,向指定的数据源index中写入数据。<br>**原子化服务API:** 从API version 19开始,该接口支持在原子化服务中使用。 | 254| onTotalCount<sup>19+</sup> | () => number | 否 | 数据项总数计算函数,返回值可以不等于数据源长度。推荐使用onTotalCount代替totalCount。同时设置totalCount与onTotalCount时,忽略totalCount。<br>取值范围:[0, +∞)<br>**原子化服务API:** 从API version 19开始,该接口支持在原子化服务中使用。 | 255 256### totalCount:期望加载的数据长度 257 258totalCount表示期望加载的数据长度,默认为原数组长度,可以大于已加载数据项的数量。arr.length表示数据源长度,以下为totalCount的处理规则: 259 260- totalCount缺省或是非自然数时,totalCount默认为arr.length,列表正常滚动。 261- 0 <= totalCount < arr.length时,界面中只渲染区间[0, totalCount - 1]范围内的数据。 262- totalCount > arr.length时,代表Repeat将渲染区间[0, totalCount - 1]范围内的数据,滚动条样式根据totalCount值变化。 263 264> **注意:** 265> 266> 当totalCount > arr.length时,在父组件容器滚动过程中,应用需要保证在列表即将滑动到数据源末尾时请求后续数据。开发者需要对数据请求的错误场景(如网络延迟)进行保护操作,直到数据源全部加载完成,否则列表滑动过程中会出现滚动效果异常。解决方案见[totalCount值大于数据源长度](../../../ui/state-management/arkts-new-rendering-control-repeat.md#totalcount值大于数据源长度)。 267 268### onLazyLoading<sup>19+</sup>:数据精准懒加载 269 270onLazyLoading从API version 19开始支持,需在懒加载场景下使用。开发者可设置自定义方法,用于向指定的数据源index中写入数据。以下为onLazyLoading的处理规则: 271 272- 在Repeat读取数据源中某一index处对应数据前,会先检查此index处是否存在数据。 273- 当不存在数据,但开发者提供了onLazyLoading方法,Repeat将调用此方法。 274- 在onLazyLoading方法中,开发者需要向Repeat指定的index中写入数据,方式如下:`arr[index] = ...`。需要注意的是,不允许使用除`[]`以外的数组操作,且不允许写入指定index以外的元素,否则系统将抛出异常。 275- onLazyLoading方法执行完成后,若指定index中仍无数据,将导致渲染异常。 276 277> **注意:** 278> 279> - 当使用onLazyLoading时,建议与onTotalCount配合使用,不建议使用totalCount。 280> - 若期望数据源长度大于实际数据源长度,推荐使用onLazyLoading。 281> - onLazyLoading方法中应避免高耗时操作。若数据加载耗时较长,建议先在onLazyLoading方法中为此数据创建占位符,再创建异步任务加载数据。 282> - 当使用onLazyLoading,并设置onTotalCount为`arr.length + 1`时,可实现数据的无限加载。需要注意,在此场景下,开发者需要提供首屏显示所需的初始数据,并建议设置父容器组件`cachedCount > 0`,否则将会导致渲染异常。若与Swiper-Loop模式同时使用,停留在`index = 0`处时将导致onLazyLoading方法被持续触发,建议避免与Swiper-Loop模式同时使用。此外,开发者需要关注内存消耗情况,避免因数据持续加载而导致内存过量消耗。 283 284### onTotalCount<sup>19+</sup>:计算期望的数据长度 285 286onTotalCount从API version 19开始支持,需在懒加载场景下使用。开发者可设置自定义方法,用于计算期望的数组长度。其返回值应当为自然数,可以不等于实际数据源长度arr.length。以下为onTotalCount的处理规则: 287 288- 当onTotalCount返回值为非自然数时,使用arr.length代替返回值,列表正常滚动。 289- 当0 <= onTotalCount返回值 < arr.length时,界面中只渲染区间[0, onTotalCount返回值 - 1]范围内的数据。 290- 当onTotalCount返回值 > arr.length时,代表Repeat将渲染区间[0, onTotalCount返回值 - 1]范围内的数据,滚动条样式根据onTotalCount返回值变化。 291 292> **注意:** 293> 294> - 相较于totalCount,Repeat可在需要时主动调用onTotalCount方法,更新期望数据长度。 295> - totalCount与onTotalCount最多设置一个。如果均未设置,则采用默认值arr.length;如果同时设置,则忽略totalCount。 296> - 当onTotalCount返回值 > arr.length时,建议配合使用onLazyLoading实现数据懒加载。 297 298### 示例 299 300```ts 301// arr是Array<string>类型的数组,在List容器组件中使用Repeat,并打开virtualScroll 302// 将加载的数据项总数设为数据源的长度,并开启复用功能 303List() { 304 Repeat<string>(this.arr) 305 .each((obj: RepeatItem<string>) => { ListItem() { Text(obj.item) }}) 306 .virtualScroll( { totalCount: this.arr.length, reusable: true } ) 307} 308 309// 假设数据项总数为100,首屏渲染需3项数据 310// 初始数组提供前3项数据(arr = ['No.0', 'No.1', 'No.2']),并开启数据懒加载功能 311List() { 312 Repeat<string>(this.arr) 313 .each((obj: RepeatItem<string>) => { ListItem() { Text(obj.item) }}) 314 .virtualScroll({ 315 onTotalCount: () => { return 100; }, 316 onLazyLoading: (index: number) => { this.arr[index] = `No.${index}`; } 317 }) 318} 319``` 320 321## RepeatItemBuilder\<T\> 322 323type RepeatItemBuilder\<T\> = (repeatItem: RepeatItem\<T\>) => void 324 325**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 326 327**系统能力:** SystemCapability.ArkUI.ArkUI.Full 328 329**参数:** 330 331| 参数名 | 类型 | 必填 | 说明 | 332| ---------- | ------------- | --------------------------------------- | --------------------------------------- | 333| repeatItem | [RepeatItem](#repeatitemt)\<T\> | 否 | 将item和index结合到一起的一个状态变量。 | 334 335## TemplateOptions对象说明 336 337**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 338 339**系统能力:** SystemCapability.ArkUI.ArkUI.Full 340 341| 名称 | 类型 | 必填 | 说明 | 342| ----------- | ------ | ---- | ------------------------------------------------------------ | 343| cachedCount | number | 否 | 当前template的缓存池中可缓存子组件节点的最大数量。取值范围是[0, +∞)。默认值为屏上节点与预加载节点的个数之和。当屏上节点与预加载节点的个数之和增多时,cachedCount也会对应增长。需要注意cachedCount数量不会减少。| 344 345当cachedCount值被设置为当前template在屏上显示的最大节点数量时,Repeat会做到最大程度的复用。然而当屏上没有当前template的节点时,缓存池不会释放的同时应用内存增大。需要开发者根据具体情况自行把控。 346 347- 当cachedCount缺省时,框架会分别对不同template,根据屏上节点+预加载节点的个数之和来计算cachedCount。当屏上节点+预加载节点的个数之和增多时,cachedCount也会对应增长。需要注意cachedCount数量不会减少。 348- 显式指定cachedCount,推荐设置成和屏幕上节点个数一致。需要注意,不推荐设置cachedCount小于2,因为这会导致在快速滑动场景下创建新的节点,从而造成性能劣化。 349 350> **注意:** 351> 352> 滚动容器组件属性`.cachedCount()`和Repeat组件属性`.template()`的参数`cachedCount`都是为了平衡性能和内存,但是含义是不同的。 353> - 滚动容器组件`.cachedCount()`:是指在可见范围外预加载的节点,这些节点会位于组件树上,但不是可见范围内。List/Grid等容器组件会额外渲染这些可见范围外的节点,从而达到其性能收益。Repeat会将这些节点视为“可见”的。 354> - `.template()`中的`cachedCount`: 是指Repeat视其为“不可见”的节点,这些空闲的节点框架会暂时保存,在需要使用时进行更新,从而实现复用。 355 356**示例:** 357```ts 358// arr是Array<string>类型的数组,在List容器组件中使用Repeat,并打开virtualScroll 359// 创建模板temp,该模板为数据创建Text组件,所有数据项都使用temp模板 360// 将temp模板的最大缓存节点数量设为2 361List() { 362 Repeat<string>(this.arr) 363 .each((obj: RepeatItem<string>) => {}) 364 .virtualScroll() 365 .template('temp', (obj: RepeatItem<string>) => { ListItem() { Text(obj.item) }}, { cachedCount: 2 }) 366 .templateId((item: string, index: number) => { return 'temp' }) 367} 368``` 369 370## TemplateTypedFunc\<T\> 371 372type TemplateTypedFunc\<T\> = (item: T, index: number) => string 373 374**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。 375 376**系统能力:** SystemCapability.ArkUI.ArkUI.Full 377 378**参数:** 379 380| 参数名 | 类型 | 必填 | 说明 | 381| ------ | ------ | ---- | -------------------------------------------- | 382| item | T | 否 | arr中每一个数据项。T为开发者传入的数据类型。 | 383| index | number | 否 | 当前数据项对应的索引。 |