• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# 循环渲染
2
3开发框架提供循环渲染(ForEach组件)来迭代数组,并为每个数组项创建相应的组件。ForEach定义如下:
4
5
6```
7ForEach(
8    arr: any[], // Array to be iterated
9    itemGenerator: (item: any, index?: number) => void, // child component generator
10    keyGenerator?: (item: any, index?: number) => string // (optional) Unique key generator, which is recommended.
11)
12```
13
14
15## ForEach
16
17
18ForEach(arr: any[],itemGenerator: (item: any, index?: number) => void, keyGenerator?: (item: any, index?: number) => string):void
19
20
21表1 参数说明
22
23| 参数名 | 参数类型 | 必填 | 默认值 | 参数描述 |
24| -------- | -------- | -------- | -------- | -------- |
25| arr | any[] | 是 | - | 必须是数组,允许空数组,空数组场景下不会创建子组件。同时允许设置返回值为数组类型的函数,例如arr.slice(1, 3),设置的函数不得改变包括数组本身在内的任何状态变量,如Array.spliceArray.sortArray.reverse这些改变原数组的函数。 |
26| itemGenerator | (item: any, index?: number) => void | 是 | - | 生成子组件的lambda函数,为给定数组项生成一个或多个子组件,单个组件和子组件列表必须括在大括号“{....}”中。 |
27| keyGenerator | (item: any, index?: number) => string | 否 | - | 匿名参数,用于给定数组项生成唯一且稳定的键值。当子项在数组中的位置更改时,子项的键值不得更改,当数组中的子项被新项替换时,被替换项的键值和新项的键值必须不同。键值生成器的功能是可选的,但是,为了使开发框架能够更好地识别数组更改,提高性能,建议提供。如将数组反向时,如果没有提供键值生成器,则ForEach中的所有节点都将重建。 |
28
29
30> ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:**
31> - 必须在容器组件内使用;
32>
33> - 生成的子组件允许在ForEach的父容器组件中,允许子组件生成器函数中包含if/else条件渲染,同时也允许ForEach包含在if/else条件渲染语句中;
34>
35> - 子项生成器函数的调用顺序不一定和数组中的数据项相同,在开发过程中不要假设子项生成器和键值生成器函数是否执行以及执行顺序。如下示例可能无法正常工作:
36>   ```
37>   ForEach(anArray, item => {Text(`${++counter}. item.label`)})
38>   ```
39>
40>   正确的示例如下:
41>
42>   ```
43>   ForEach(anArray.map((item1, index1) => { return { i: index1 + 1, data: item1 }; }),
44>           item => Text(`${item.i}. item.data.label`),
45>           item => item.data.id.toString())
46>   ```
47
48
49## 示例
50
51简单类型数组示例:
52
53```
54@Entry
55@Component
56struct MyComponent {
57    @State arr: number[] = [10, 20, 30]
58    build() {
59        Column() {
60            Button() {
61                Text('Reverse Array')
62            }.onClick(() => {
63                this.arr.reverse()
64            })
65
66            ForEach(this.arr,                         // Parameter 1: array to be iterated
67                    (item: number) => {               // Parameter 2: item generator
68                        Text(`item value: ${item}`)
69                        Divider()
70                    },
71                    (item: number) => item.toString() // Parameter 3: unique key generator, which is optional but recommended.
72            )
73        }
74    }
75}
76```
77
78复杂类型数组示例:
79```
80class Month {
81  year: number
82  month: number
83  days: Array<number>
84
85  constructor(year, month, days) {
86    this.year = year;
87    this.month = month;
88    this.days = days;
89  }
90}
91
92@Entry
93@Component
94struct Calendar1 {
95// simulate with 6 months
96  @State calendar: Month[] = [
97    new Month(2020, 1, [...Array(31).keys()]),
98    new Month(2020, 2, [...Array(28).keys()]),
99    new Month(2020, 3, [...Array(31).keys()]),
100    new Month(2020, 4, [...Array(30).keys()]),
101    new Month(2020, 5, [...Array(31).keys()]),
102    new Month(2020, 6, [...Array(30).keys()]),
103  ]
104
105  build() {
106    Column() {
107      Button('next month')
108        .onClick(() => {
109          this.calendar.shift()
110          this.calendar.push({
111            year: 2020,
112            month: 7,
113            days: [...Array(31)
114              .keys()]
115          })
116        })
117      ForEach(this.calendar,
118        (item: Month) => {
119          Text('month:' + item.month)
120            .fontSize(30)
121            .padding(20)
122          Grid() {
123            ForEach(item.days,
124              (day: number) => {
125                GridItem() {
126                  Text((day + 1).toString())
127                    .fontSize(30)
128                }
129              },
130              (day: number) => day.toString())
131          }
132          .columnsTemplate('1fr 1fr 1fr 1fr 1fr 1fr 1fr')
133          .rowsGap(20)
134        },
135        // field is used together with year and month as the unique ID of the month.
136        (item: Month) => (item.year * 12 + item.month).toString())
137    }
138  }
139}
140```
141