HarmonyOS开发实战:笔友-条件渲染与可见性控制:if/Visibility 对比 📅 2026/7/26 4:09:10 前言在 ArkUI 声明式开发范式中条件渲染和可见性控制是两种不同的 UI 控制策略。if/else通过条件判断决定是否创建组件而Visibility通过控制组件的可见性属性决定是否显示。它们各有适用场景错误的选择可能导致性能问题或状态丢失。本文将以开源鸿蒙笔友通信应用 xiexin 的SplashPage.ets、Index.ets、ComposePage.ets为蓝本详细剖析if/else和Visibility的语义、差异、性能对比以及它们在不同场景下的最佳实践。提示本文假设你已经了解 ArkUI 声明式开发的基本概念。如果还不熟悉建议先阅读前十七篇文章。一、条件渲染的两种方式1.1 if/else 条件渲染if/else通过条件判断决定是否创建组件// SplashPage.ets — if/else 切换按钮if(this.currentPage2){Button(开始写信).fontSize(16).fontColor(AppColors.WHITE).backgroundColor(AppColors.PRIMARY).borderRadius(24).width(200).height(48).onClick((){router.replaceUrl({url:pages/Index});})}else{Button(下一步).fontSize(16).fontColor(AppColors.PRIMARY).backgroundColor(AppColors.AMBER_LIGHT).borderRadius(24).width(200).height(48).onClick((){this.currentPagethis.currentPage1;})}1.2 Visibility 可见性控制Visibility通过属性控制组件是否可见// Visibility 的三种状态Visibility.None// 完全不可见不占布局空间Visibility.Hidden// 不可见但保留布局占位Visibility.Visible// 可见// 使用示例Text(隐藏文字).visibility(Visibility.Hidden)二、if/else 与 Visibility 的核心差异2.1 对比表格维度if/elseVisibility组件创建条件为 true 时创建始终创建内存占用条件为 false 时不占用始终占用内存布局空间条件为 false 时不占布局None不占Hidden占位状态保留条件变化时销毁重建状态丢失状态始终保留适用场景不常切换、内容较多频繁切换、内容较少性能开销创建/销毁有开销始终存在无切换开销2.2 选择决策树组件是否需要频繁切换显示/隐藏 ├── 是 → Visibility │ 组件是否需要保留状态 │ ├── 是 → Visibility.Hidden保留占位 │ └── 否 → Visibility.None不占布局 └── 否 → if/else 组件内容是否较多 ├── 是 → if/else减少内存占用 └── 否 → if/else默认选择三、xiexin 中的条件渲染3.1 SplashPage 的按钮切换// SplashPage.ets — 使用 if/else 切换按钮if(this.currentPage2){Button(开始写信).fontSize(16).fontColor(AppColors.WHITE).backgroundColor(AppColors.PRIMARY).borderRadius(24).width(200).height(48).fontWeight(FontWeight.Medium).onClick((){router.replaceUrl({url:pages/Index});})}else{Button(下一步).fontSize(16).fontColor(AppColors.PRIMARY).backgroundColor(AppColors.AMBER_LIGHT).borderRadius(24).width(200).height(48).fontWeight(FontWeight.Medium).onClick((){this.currentPagethis.currentPage1;})}这里使用if/else是正确的选择因为切换频率低用户只会在引导页翻页时切换一次组件内容少按钮只有 10 行代码创建/销毁开销小状态不保留切换按钮时不需要保留上一个按钮的状态3.2 Index 页面的空状态判断// Index.ets — 使用 if/else 判断空状态if(this.letters.length0){EmptyState({title:还没有信件去写第一封吧,subtitle:每一封信都是一段温暖的旅程})}else{Scroll(){Column({space:12}){ForEach(this.getSortedLetters(),(letter:Letter){this.LetterCard(letter)},(letter:Letter)letter.id.toString())}.padding({left:16,right:16,bottom:20})}.layoutWeight(1).scrollBar(BarState.Off)}这里使用if/else是正确的选择因为切换频率低从空状态到有信件只切换一次内容差异大空状态和信件列表的 UI 完全不同内存优化空状态时不会创建 100 个 ListItem 组件3.3 ComposePage 的面板展开// ComposePage.ets — 使用 State 布尔值控制面板展开StateshowHonorificPanel:booleanfalse;StateshowGreetingPanel:booleanfalse;StateshowClosingPanel:booleanfalse;StateshowWordPanel:booleanfalse;StateshowPaperPanel:booleanfalse;StateshowFormatPanel:booleanfalse;// 在 build 中使用 if 条件渲染if(this.showHonorificPanel){this.HonorificPanel()}if(this.showGreetingPanel){this.GreetingPanel()}这里使用if条件渲染但应该考虑Visibility的优化// 优化使用 Visibility 保留面板展开时的滚动位置HonorificPanel().visibility(this.showHonorificPanel?Visibility.Visible:Visibility.None)四、if/else 的常见陷阱4.1 状态丢失// 问题if/else 切换时子组件状态丢失EntryComponentstruct MyComponent{StateshowInput:booleanfalse;build(){Column(){if(this.showInput){TextInput({placeholder:输入内容})}Button(切换).onClick((){this.showInput!this.showInput;})}}}当showInput从true变为false再变为true时TextInput组件被销毁重建用户输入的内容丢失。4.2 动画中断// 问题if/else 切换时动画被中断if(this.isVisible){Text(Hello).opacity(1).animation({duration:300})}else{// 组件不存在动画无法播放}4.3 性能问题// 问题频繁切换时if/else 导致大量创建/销毁if(this.isVisible){ForEach(this.largeArray,(item){// 大量组件},(item)item.id.toString())}五、Visibility 的常见陷阱5.1 布局空间问题// Visibility.Hidden 保留布局空间Column(){Text(标题).visibility(Visibility.Hidden)// 标题不可见但占位还在Text(内容)}5.2 与动画的配合// 使用 opacity 实现平滑过渡StateisVisible:booleanfalse;Text(Hello).opacity(this.isVisible?1:0).animation({duration:300,curve:Curve.EaseOut})六、if/else 与 Visibility 的配合使用6.1 组合策略// 组合使用if/else 控制创建Visibility 控制显示StateisComponentCreated:booleanfalse;StateisComponentVisible:booleanfalse;if(this.isComponentCreated){Text(Hello).visibility(this.isComponentVisible?Visibility.Visible:Visibility.Hidden)}6.2 实际应用// 场景弹窗的创建和显示StateisDialogCreated:booleanfalse;StateisDialogVisible:booleanfalse;// 创建弹窗仅一次if(this.isDialogCreated){CustomDialog({visible:this.isDialogVisible,onClose:(){this.isDialogVisiblefalse;}})}// 显示/隐藏弹窗多次切换Button(显示弹窗).onClick((){this.isDialogCreatedtrue;this.isDialogVisibletrue;})七、xiexin 中的可见性控制优化7.1 当前实现xiexin 当前主要使用if/else进行条件渲染// SplashPage: if/else 切换按钮if(this.currentPage2){/* 开始写信按钮 */}else{/* 下一步按钮 */}// Index: if/else 判断空状态if(this.letters.length0){/* 空状态 */}else{/* 信件列表 */}// ComposePage: if 控制面板展开if(this.showHonorificPanel){/* 称谓面板 */}7.2 优化建议当前位置当前方式建议方式理由SplashPage 按钮if/else保持 if/else切换频率低内容简单Index 空状态if/else保持 if/else内容差异大内存优化ComposePage 面板if改为 Visibility面板切换频繁需保留状态八、条件渲染的性能对比8.1 创建/销毁开销对比项if/elseVisibility首次创建需要创建需要创建条件变化销毁重建不需要创建多次切换每次创建/销毁无额外开销8.2 内存占用对比项if/elseVisibility条件为 false不占用内存占用内存条件为 true占用内存占用内存1000 项列表仅创建 1000 项始终创建 1000 项九、Visibility 与动画的配合9.1 淡入淡出效果EntryComponentstruct FadeExample{StateisVisible:booleanfalse;build(){Column(){Text(Hello).opacity(this.isVisible?1:0).animation({duration:300,curve:Curve.EaseOut})Button(切换).onClick((){this.isVisible!this.isVisible;})}}}9.2 滑动展开效果EntryComponentstruct SlideExample{StateisExpanded:booleanfalse;build(){Column(){Button(展开).onClick((){animateTo({duration:300},(){this.isExpanded!this.isExpanded;})})// 使用 if 控制创建动画控制显示if(this.isExpanded){Text(内容).opacity(1).animation({duration:300})}}}}十、从 xiexin 看条件渲染与可见性控制xiexin 中条件渲染的使用体现了场景决定选择的原则引导页按钮切换使用if/else因为切换频率低、内容简单空状态判断使用if/else因为内容差异大、内存占用差别大编辑面板展开使用if实际上应该用Visibility因为切换频繁、需要保留状态每个场景的选择都基于实际的业务需求而非盲目使用某一种方式。总结本文详细剖析了 HarmonyOS ArkUI 的if/else条件渲染和Visibility可见性控制的语义、差异、性能对比以及它们在不同场景下的最佳实践。理解条件渲染与可见性控制的关键是把握两个原则创建原则if/else 决定是否创建和显示原则Visibility 决定是否显示。创建原则适用于不常切换、内容较多的场景显示原则适用于频繁切换、需要保留状态的场景。至此我们已经完成了 HarmonyOS 应用开发实战系列的第二阶段——ArkUI 声明式 UI 进阶。从下一篇文章开始我们将进入第三阶段——组件化与通用组件深入剖析 xiexin 中如何通过组件封装实现 UI 复用。如果这篇文章对你有帮助欢迎点赞、收藏⭐、关注你的支持是我持续创作的动力相关资源开源鸿蒙跨平台社区https://openharmonycrossplatform.csdn.netHarmonyOS 渲染控制概述https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-rendering-control-overviewHarmonyOS if/else 条件渲染https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-rendering-control-ifHarmonyOS ForEach 渲染控制https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-rendering-control-foreachHarmonyOS LazyForEach 渲染控制https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-rendering-control-lazyforeachHarmonyOS 高性能编程实践https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-high-performance-programmingHarmonyOS 动画概述https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-animationHarmonyOS 状态管理概述https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-state-management-overviewHarmonyOS 自定义组件https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-custom-components