1# ForEach
2
3ForEach接口基于数组类型数据来进行循环渲染。
4
5> **说明:**
6>
7> 本模块首批接口从API version 7开始支持。后续版本的新增接口,采用上角标单独标记接口的起始版本。
8
9开发者指南见:[ForEach开发者指南](../../../quick-start/arkts-rendering-control-foreach.md)
10
11## 接口
12
13ForEach(arr: Array\<any\>,itemGenerator: (item: any, index: number) => void,keyGenerator?: (item: any, index: number) => string,)
14
15ForEach接口基于数组类型数据来进行循环渲染,需要与容器组件配合使用,且接口返回的组件应当是允许包含在ForEach父容器组件中的子组件。例如,ListItem组件要求ForEach的父容器组件必须为[List组件](../../../reference/apis-arkui/arkui-ts/ts-container-list.md)。
16
17**卡片能力:** 从API version 9开始,该接口支持在ArkTS卡片中使用。
18
19**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。
20
21**系统能力:** SystemCapability.ArkUI.ArkUI.Full
22
23**参数:**
24
25| 参数名        | 类型                                    | 必填 | 说明                                                         |
26| ------------- | --------------------------------------- | ---- | ------------------------------------------------------------ |
27| arr           | Array\<Object\>                         | 是   | 数据源,为`Array`类型的数组。<br/>**说明:**<br/>- 可以设置为空数组,此时不会创建子组件。<br/>- 可以设置返回值为数组类型的函数,例如`arr.slice(1, 3)`,但设置的函数不应改变包括数组本身在内的任何状态变量,例如不应使用`Array.splice()`,`Array.sort()`或`Array.reverse()`这些会改变原数组的函数。 |
28| itemGenerator | (item: Object, index: number) => void   | 是   | 组件生成函数。<br/>- 为数组中的每个元素创建对应的组件。<br/>- `item`参数:`arr`数组中的数据项。<br/>- `index`参数(可选):`arr`数组中的数据项索引。<br/>**说明:**<br/>- 组件的类型必须是`ForEach`的父容器所允许的。例如,`ListItem`组件要求`ForEach`的父容器组件必须为`List`组件。 |
29| keyGenerator  | (item: Object, index: number) => string | 否   | 键值生成函数。<br/>- 为数据源`arr`的每个数组项生成唯一且持久的键值。函数返回值为开发者自定义的键值生成规则。<br/>- `item`参数:`arr`数组中的数据项。<br/>- `index`参数(可选):`arr`数组中的数据项索引。<br/>**说明:**<br/>- 如果函数缺省,框架默认的键值生成函数为`(item: T, index: number) => { return index + '__' + JSON.stringify(item); }`<br/>- 键值生成函数不应改变任何组件状态。 |
30
31> **说明:**
32>
33> - `ForEach`的`itemGenerator`函数可以包含`if/else`条件渲染逻辑。另外,也可以在`if/else`条件渲染语句中使用`ForEach`组件。
34> - 在初始化渲染时,`ForEach`会加载数据源的所有数据,并为每个数据项创建对应的组件,然后将其挂载到渲染树上。如果数据源非常大或有特定的性能需求,建议使用`LazyForEach`组件。
35
36## 属性
37
38继承自[DynamicNode](#dynamicnode12)。
39
40## DynamicNode<sup>12+</sup>
41
42定义节点。
43
44**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。
45
46**系统能力:** SystemCapability.ArkUI.ArkUI.Full
47
48### onMove<sup>12+</sup>
49
50onMove(handler: Optional\<OnMoveHandler\>): T;
51
52拖拽排序数据移动回调。只有在List组件中使用,并且ForEach每次迭代都生成一个ListItem组件时才生效拖拽排序。
53
54**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。
55
56**系统能力:** SystemCapability.ArkUI.ArkUI.Full
57
58**参数:**
59
60| 参数名 | 类型      | 必填 | 说明       |
61| ------ | --------- | ---- | ---------- |
62| handler  | Optional\<OnMoveHandler\> | 是   | 拖拽动作。 |
63
64## OnMoveHandler
65
66type OnMoveHandler = (from: number, to: number) => void;
67
68定义数据源拖拽回调。
69
70**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。
71
72**系统能力:** SystemCapability.ArkUI.ArkUI.Full
73
74**参数:**
75
76| 参数名 | 类型      | 必填 | 说明       |
77| ------ | --------- | ---- | ---------- |
78| from  | number | 是   | 数据源移动起始索引号。 |
79| to  | number | 是   | 数据源移动目标索引号。 |
80
81## 示例
82
83下面的示例展示了ForEach在List组件内使用时的拖拽效果。
84
85```ts
86@Entry
87@Component
88struct ForEachSort {
89  @State arr: Array<string> = [];
90
91  build() {
92    Row() {
93      List() {
94        ForEach(this.arr, (item: string) => {
95          ListItem() {
96            Text(item.toString())
97              .fontSize(16)
98              .textAlign(TextAlign.Center)
99              .size({height: 100, width: "100%"})
100          }.margin(10)
101          .borderRadius(10)
102          .backgroundColor("#FFFFFFFF")
103        }, (item: string) => item)
104          .onMove((from:number, to:number) => {
105            let tmp = this.arr.splice(from, 1);
106            this.arr.splice(to, 0, tmp[0]);
107          })
108      }
109      .width('100%')
110      .height('100%')
111      .backgroundColor("#FFDCDCDC")
112    }
113  }
114  aboutToAppear(): void {
115    for (let i = 0; i < 100; i++) {
116      this.arr.push(i.toString());
117    }
118  }
119}
120```
121