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 = -1
build() {
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