📚鸿蒙开发往期学习笔录✒️:
✒️ 鸿蒙(OpenHarmony)南向开发保姆级知识点汇总~
✒️ 鸿蒙应用开发与鸿蒙系统开发哪个更有前景?
✒️ 嵌入式开发适不适合做鸿蒙南向开发?看完这篇你就了解了~
✒️ 对于大前端开发来说,转鸿蒙开发究竟是福还是祸?
✒️ 鸿蒙岗位需求突增!移动端、PC端、IoT到底该怎么选?
✒️ 记录一场鸿蒙开发岗位面试经历~
✒️ 持续更新中……
开发者可以通过条件渲染或显隐控制两种方式来实现组件在显示和隐藏间的切换。本文从两者原理机制的区别出发,对二者适用场景分别进行说明,实现相应适用场景的示例并给出性能对比数据。
原理机制
条件渲染
if/else条件渲染是ArkUI应用开发框架提供的渲染控制的能力之一。条件渲染可根据应用的不同状态,渲染对应分支下的UI描述。条件渲染的作用机制如下:
- 页面初始构建时,会评估条件语句,构建适用分支的组件,若缺少适用分支,则不构建任何内容。
- 应用状态变化时,会重新评估条件语句,删除不适用分支的组件,构建适用分支的组件,若缺少适用分支,则不构建任何内容。
显隐控制
显隐控制visibility是ArkUI应用开发框架提供的组件通用属性之一。开发者可以通过设定组件属性visibility不同的属性值,进而控制组件的显隐状态。visibility属性值及其描述如下:
名称 | 描述 |
---|---|
Visible | 组件状态为可见 |
Hidden | 组件状态为不可见,但参与布局、进行占位 |
None | 组件状态为不可见,不参与布局、不进行占位 |
机制区别
具体针对实现组件显示和隐藏间切换的场景,条件渲染和显隐控制的作用机制区别总结如下:
机制描述 | 条件渲染 | 显隐控制 |
---|---|---|
页面初始构建时,若组件隐藏,组件是否会被创建 | 否 | 是 |
若组件由显示变为隐藏时,组件是否会被销毁、从组件树取下 | 是 | 否 |
若组件隐藏时,是否占位 | 否 | 可以配置 |
适用场景
通过条件渲染或显隐控制,实现组件的显示和隐藏间的切换,两者的适用场景分别如下:
条件渲染的适用场景:
- 在应用冷启动阶段,应用加载绘制首页时,如果组件初始不需要显示,建议使用条件渲染替代显隐控制,以减少渲染时间,加快启动速度。
- 如果组件不会较频繁地在显示和隐藏间切换,或者大部分时间不需要显示,建议使用条件渲染替代显隐控制,以减少界面复杂度、减少嵌套层次,提升性能。
- 如果被控制的组件所占内存庞大,开发者优先考虑内存时,建议使用条件渲染替代显隐控制,以即时销毁不需要显示的组件,节省内存。
- 如果组件子树结构比较复杂,且反复切换条件渲染的控制分支,建议使用条件渲染配合组件复用机制,提升应用性能。
- 如果切换项仅涉及部分组件的情况,且反复切换条件渲染的控制分支,建议使用条件渲染配合容器限制,精准控制组件更新的范围,提升应用性能。
显隐控制的适用场景:
- 如果组件频繁地在显示和隐藏间切换时,建议使用显隐控制替代条件渲染,以避免组件的频繁创建与销毁,提升性能。
- 如果组件隐藏后,在页面布局中,需要保持占位,建议适用显隐控制。
显隐控制
针对显示和隐藏间频繁切换的场景,下面示例通过按钮点击,实现1000张图片显示与隐藏,来简单复现该场景,并进行正反例性能数据的对比。
反例
使用条件循环实现显示和隐藏间的切换。
@Entry
@Component
struct WorseUseIf {
@State isVisible: boolean = true;
private data: number[] = [];
aboutToAppear() {
for (let i: number = 0; i < 1000; i++) {
this.data.push(i);
}
}
build() {
Column() {
Button("Switch visible and hidden").onClick(() => {
this.isVisible = !(this.isVisible);
}).width('100%')
Stack() {
if (this.isVisible) {
// 使用条件渲染切换,会频繁创建与销毁组件
Column() {
ForEach(this.data, (item: number) => {
Image($r('app.media.icon')).width('25%').height('12.5%')
}, (item: number) => item.toString())
}
}
}
}
}
}
正例
使用显隐控制实现显示和隐藏间的切换。
@Entry
@Component
struct BetterUseVisibility {
@State isVisible: boolean = true;
private data: number[] = [];
aboutToAppear() {
for (let i: number = 0; i < 1000; i++) {
this.data.push(i);
}
}
build() {
Column() {
Button("Switch visible and hidden").onClick(() => {
this.isVisible = !(this.isVisible);
}).width('100%')
Scroll() {
Column() {
ForEach(this.data, (item: number) => {
Image($r('app.media.icon')).width('25%'