if/else
使用规则
- 支持if、else和else if语句。
- if、else if后跟随的条件语句可以使用状态变量。
- 允许在容器组件内使用,通过条件渲染语句构建不同的子组件。
- 条件渲染语句在涉及到组件的父子关系时是“透明”的,当父组件和子组件之间存在一个或多个if语句时,必须遵守父组件关于子组件使用的规则。
- 每个分支内部的构建函数必须遵循构建函数的规则,并创建一个或多个组件。无法创建组件的空构建函数会产生语法错误。
- 某些容器组件限制子组件的类型或数量,将条件渲染语句用于这些组件内时,这些限制将同样应用于条件渲染语句内创建的组件。例如,Grid容器组件的子组件仅支持GridItem组件,在Grid内使用条件渲染语句时,条件渲染语句内仅允许使用GridItem组件。
更新机制
当if、else if后跟随的状态判断中使用的状态变量值变化时,条件渲染语句会进行更新,更新步骤如下:
- 评估if和else if的状态判断条件,如果分支没有变化,无需执行以下步骤。如果分支有变化,则执行2、3步骤:
- 删除此前构建的所有子组件。
- 执行新分支的构造函数,将获取到的组件添加到if父容器中。如果缺少适用的else分支,则不构建任何内容。
条件可以包括Typescript表达式。对于构造函数中的表达式,此类表达式不得更改应用程序状态。
示例
@Entry
@Component
struct Index {SelectData: { value: string }[] = [{ value: "霍建华" }, { value: "周深" }, { value: "杨丽萍" }]@State selected: number = -1build() {Column() {Select(this.SelectData).selected(0).value("请选择").onSelect((index) => {this.selected = index})if (this.selected === 0) {Text("演员")} else if (this.selected === 1) {Text("歌手")} else if (this.selected === 2) {Text("舞蹈家")} else {Text("普通人")}}.height("100%").width("100%")}
}
ForEach
接口
ForEach(
arr: Array,
itemGenerator: (item: any, index: number) => void,
keyGenerator?: (item: any, index: number) => string
)
参数
参数名 | 参数类型 | 必填 | 参数描述 |
---|---|---|---|
arr | Array<any> | 是 | 数据源,为Array类型的数组。 说明: - 可以设置为空数组,此时不会创建子组件。 - 可以设置返回值为数组类型的函数,例如arr.slice(1, 3),但设置的函数不应改变包括数组本身在内的任何状态变量,例如不应使用Array.splice(),Array.sort()或Array.reverse()这些会改变原数组的函数。 |
itemGenerator | (item: any, index: number) => void | 是 | 组件生成函数。 - 为数组中的每个元素创建对应的组件。 - item参数:arr数组中的数据项。 - index参数(可选):arr数组中的数据项索引。 说明: - 组件的类型必须是ForEach的父容器所允许的。例如,ListItem组件要求ForEach的父容器组件必须为List组件。 |
keyGenerator | (item: any, index: number) => string | 否 | 键值生成函数。 - 为数据源arr的每个数组项生成唯一且持久的键值。函数返回值为开发者自定义的键值生成规则。 - item参数:arr数组中的数据项。- index参数(可选):arr数组中的数据项索引。 说明: - 如果函数缺省,框架默认的键值生成函数为(item: T, index: number) => { return index + '__' + JSON.stringify(item); } - 键值生成函数不应改变任何组件状态。 |
键值生成规则
默认的键值生成函数
(item: any, index: number) => { return index + '__' + JSON.stringify(item); }
示例
@Entry
@Component
struct Index {@State arrObj: {id: number,name: string}[] = [{ id: 1, name: "lili" },{ id: 2, name: "Tom" },{ id: 3, name: "Janny" }]build() {Column() {ForEach(this.arrObj, (item) => {Text(`${new Date().getTime()}---${item.name}`)}, (item) => JSON.stringify(item))Button("尾部新增一项").onClick(() => {this.arrObj.push({ id: this.arrObj.length, name: "丽萍" })})Button("调换位置").onClick(() => {this.arrObj = [this.arrObj[2], this.arrObj[0], this.arrObj[1]]})}.width('100%').height('100%')}
}
使用建议
- 尽量避免在最终生成的键中包含索引(index)。
- 当处理对象数组时,建议使用对象中的唯一标识符(如 id)作为键。
- 如果处理基本数据类型的数组,必须确保数组项无重复。或者将基本数据类型数组转化为具备唯一ID属性的对象数据类型数组,再使用ID属性作为键值生成规则。
不推荐案例
开发者在使用ForEach的过程中,若对于键值生成规则的理解不够充分,可能会出现错误的使用方式。错误使用一方面会导致功能层面问题,例如渲染结果非预期,另一方面会导致性能层面问题,例如渲染性能降低。
https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V2/arkts-rendering-control-foreach-0000001524537153-V2#section221mcpsimp