前言在应用中空状态Empty State是提升用户体验的重要细节。xiexin 的EmptyState组件通过 49 行代码实现了“标题副标题按钮“的可配置空状态占位配合if/else条件渲染在列表为空时优雅地引导用户操作。本文将以CommonComponents.ets中的EmptyState组件和Index.ets中的调用为蓝本详细剖析空状态组件的设计原则、参数化配置、if/else条件渲染在空状态中的应用以及回调函数的设计模式。一、EmptyState 完整代码// CommonComponents.ets Component export struct EmptyState { Prop title: string 暂无内容; Prop subtitle: string ; Prop showButton: boolean false; Prop buttonText: string ; onButtonClick?: () void; build() { Column({ space: 16 }) { Column() { Text().fontSize(64).opacity(0.3) }.margin({ top: 60 }) Text(this.title).fontSize(16).fontColor(AppColors.TEXT_SECONDARY) if (this.subtitle.length 0) { Text(this.subtitle).fontSize(13).fontColor(AppColors.TEXT_SECONDARY).opacity(0.7) } if (this.showButton) { Button(this.buttonText).fontSize(14).fontColor(AppColors.WHITE) .backgroundColor(AppColors.PRIMARY).borderRadius(24).height(40).width(140).margin({ top: 16 }) .onClick(() { if (this.onButtonClick) { this.onButtonClick(); } }) } } .width(100%).justifyContent(FlexAlign.Center).alignItems(HorizontalAlign.Center) } }二、参数设计参数类型默认值用途titlestring‘暂无内容’主要提示文字subtitlestring‘’副标题说明showButtonbooleanfalse是否显示按钮buttonTextstring‘’按钮文字onButtonClick() voidundefined按钮点击回调三、在 Index 中的使用// 信箱 Tab 空状态 if (this.letters.length 0) { EmptyState({ title: 还没有信件去写第一封吧, subtitle: 每一封信都是一段温暖的旅程 }) } // 笔友 Tab 空状态带按钮 if (this.penPals.length 0) { EmptyState({ title: 还没有笔友邀请一位吧, subtitle: 最多5位笔友深度交流, showButton: true, buttonText: 邀请笔友, onButtonClick: () { router.pushUrl({ url: pages/AddPenPalPage }) } }) }四、装饰性元素Column() { Text().fontSize(64).opacity(0.3) }.margin({ top: 60 })五、条件渲染if (this.subtitle.length 0) { Text(this.subtitle) } if (this.showButton) { Button(this.buttonText) }六、回调函数设计onButtonClick?: () void; .onClick(() { if (this.onButtonClick) { this.onButtonClick(); } })七、扩展建议Component export struct EmptyState { Prop icon: string ; Prop iconSize: number 64; Prop title: string 暂无内容; Prop subtitle: string ; Prop showButton: boolean false; Prop buttonText: string ; onButtonClick?: () void; }八、使用场景场景标题副标题按钮信箱为空还没有信件去写第一封吧每一封信都是一段温暖的旅程无笔友为空还没有笔友邀请一位吧最多5位笔友深度交流邀请笔友九、与设计系统的集成字体标题 16sp/Regular副标题 13sp/Regular按钮 14sp/Medium颜色标题TEXT_SECONDARY按钮PRIMARY背景间距组件间距 16px按钮上部间距 16px十、无障碍适配Column().accessibilityText(this.title).accessibilityDescription(this.subtitle)十一、动画效果Text().fontSize(64).opacity(0.3).animation({ duration: 600, curve: Curve.EaseOut })十二、组件测试import { describe, it, expect } from ohos/hypium; describe(EmptyState, () { it(should display title, () { const component new EmptyState(); component.title 测试标题; expect(component.title).toBe(测试标题); }); it(should show button when showButton is true, () { const component new EmptyState(); component.showButton true; expect(component.showButton).toBeTrue(); }); });十三、性能优化条件渲染使用if/else控制按钮和副标题的渲染避免过度渲染空状态组件只在列表为空时渲染图片懒加载装饰性图标使用 emoji 而非图片资源十四、常见问题排查问题原因解决方案按钮不显示showButton为 false设置showButton: true点击无反应onButtonClick未设置传入回调函数显示异常容器未设置 width确保容器宽度为 100%十五、组件复用策略EmptyState 组件在多处复用时建议统一文案管理将空状态文案集中到Constants.ets中差异化配置通过Prop参数实现不同场景的差异化回调函数通过onButtonClick实现按钮操作的定制十六、与 Layout 组件的协作Column() { if (this.letters.length 0) { EmptyState({ title: 还没有信件, subtitle: 去写第一封吧 }) } else { Scroll() { Column({ space: 12 }) { ForEach(this.letters, (letter: Letter) { this.LetterCard(letter) }, (l: Letter) l.id.toString()) }.padding(16) }.layoutWeight(1) } }.width(100%).height(100%)十七、代码规范// 推荐明确的参数名 EmptyState({ title: 暂无内容, subtitle: 请稍后再试 }) // 不推荐模糊的布尔参数 EmptyState({ showButton: true })十八、状态管理State isEmpty: boolean false; public setEmpty(empty: boolean): void { this.isEmpty empty; }十九、版本演进EmptyState 空状态组件渲染效果二十、补充说明EmptyState 空状态组件渲染效果二十、补充说明版本新增功能变更说明v1.0基础标题副标题初始版本v1.1按钮支持新增showButton/buttonTextv1.2回调函数新增onButtonClickv2.0图标自定义新增icon/iconSize十一、深度实现分析11.1 核心原理本功能的核心原理基于 ArkUI 的响应式状态管理机制。当 State 或 Prop 装饰的变量发生变化时ArkUI 引擎会自动触发依赖该变量的 UI 部分重新渲染无需手动操作 DOM。11.2 数据流设计graph LR A[用户交互] -- B[State 变量变化] B -- C[ArkUI 引擎检测] C -- D[UI 重渲染] D -- E[用户看到新界面]11.3 性能考虑避免不必要渲染使用 Watch 控制渲染时机减少嵌套深度保持组件树扁平化合理使用缓存计算结果可缓存避免重复计算十二、实际项目应用在 xiexin 项目中本功能被应用于以下场景笔友列表展示笔友通信状态和关系阶段信件卡片展示信件内容和状态标签统计页面展示写信趋势数据和统计指标Component export struct ExampleComponent { Prop data: string[] []; build() { Column() { ForEach(this.data, (item: string) { Text(item).fontSize(14).padding(8) }, (item: string) item) } } }十三、生产环境注意事项错误处理所有异步操作需要 try-catch 包围日志记录使用 hilog 记录关键操作和异常信息性能监控使用 hiTraceMeter 进行性能埋点分析内存管理及时清理定时器和监听器避免内存泄漏try { await this.loadData(); hilog.info(0xFF00, TAG, Data loaded successfully); } catch (err) { hilog.error(0xFF00, TAG, Failed to load: %{public}s, err.message); }十四、代码审查清单Prop 变量是否已赋默认值定时器是否在 aboutToDisappear 中清理列表渲染的 keyGenerator 是否唯一且稳定条件渲染是否使用 if/else 而非 Visibility.Hidden复杂计算结果是否已缓存事件监听器是否在 aboutToDisappear 中取消注册十五、综合示例Entry Component struct DemoPage { State items: string[] [示例1, 示例2, 示例3]; State count: number 0; build() { Column({ space: 16 }) { Text(综合示例).fontSize(24).fontWeight(FontWeight.Bold) Text(计数: ${this.count}).fontSize(16) Row({ space: 8 }) { Button(增加).onClick(() { this.count }) Button(减少).onClick(() { if (this.count 0) this.count-- }) Button(重置).onClick(() { this.count 0 }) } List() { ForEach(this.items, (item: string) { ListItem() { Text(item).fontSize(14).padding(12) } }, (item: string) item) }.height(200) }.padding(16).width(100%) } }十六、相关 API 参考API说明版本要求State组件内部状态管理API 9Prop父子单向传递API 9Link父子双向同步API 9Watch状态变化监听API 9AppStorage全局状态存储API 9PersistentStorage持久化存储API 9十七、常见面试题Q1: State 和 Prop 的区别是什么A: State 是组件内部私有状态只能在当前组件内修改Prop 是父组件传递进来的数据在子组件中只能读取修改不会影响父组件。Q2: ForEach 的 keyGenerator 为什么重要A: keyGenerator 决定了 ForEach 进行 Diff 算法的依据。如果键值不稳定或重复会导致列表项渲染异常如闪烁、状态丢失等问题。十八、调试技巧使用 DevEco Profiler监控帧率和布局耗时定位卡顿根因使用 hilog打印关键日志追踪代码执行路径使用 hiTraceMeter进行性能埋点分析识别性能瓶颈使用 Watch监听状态变化调试状态更新逻辑State Watch(onDebugChange) debugValue: string ; onDebugChange(): void { console.log(Value changed to:, this.debugValue); }十九、补充说明提示本文提供的代码示例基于 HarmonyOS API 12适用于 HarmonyOS 5.0 及以上版本。如果你使用的是较低版本部分 API 可能不兼容。本文所有代码均可在 xiexin 项目中找到实际应用场景建议结合 DevEco Studio 开发工具进行调试和验证如有疑问欢迎在评论区留言讨论我会及时回复更多 HarmonyOS 开发资源请参考官方文档和开发者社区如果这篇文章对你有帮助欢迎点赞、收藏⭐、关注你的支持是我持续创作的动力相关资源开源鸿蒙跨平台社区https://openharmonycrossplatform.csdn.netHarmonyOS 应用开发指南https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/application-dev-guideHarmonyOS 状态管理概述https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-state-management-overviewHarmonyOS 高性能编程实践https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-high-performance-programmingHarmonyOS 自定义组件https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-custom-componentsHarmonyOS 组件封装https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-component-encapsulationHarmonyOS Builder 装饰器https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-builderHarmonyOS 组件复用https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-reusable二十、补充说明提示本文提供的代码示例基于 HarmonyOS API 12适用于 HarmonyOS 5.0 及以上版本。部分 API 在低版本中可能不兼容请根据实际开发环境调整。本文所有代码均可在 xiexin 项目中找到实际应用场景建议结合 DevEco Studio 开发工具进行调试和验证如有疑问欢迎在评论区留言讨论更多 HarmonyOS 开发资源请参考官方文档20.1 扩展阅读推荐HarmonyOS 应用开发指南ArkUI 声明式开发范式状态管理详解高性能编程实践20.2 代码规范建议在编写 HarmonyOS 应用时建议遵循以下代码规范组件命名使用 PascalCase如AvatarComponent变量命名使用 camelCase如avatarSize常量命名使用 UPPER_CASE如MAX_COUNT私有方法以_开头如_getAvatarColor文件命名使用 kebab-case如common-components.ets二十一、总结与最佳实践21.1 核心要点总结状态管理合理选择 State/Prop/Link/StorageProp 装饰器组件设计遵循单一职责原则保持组件聚焦性能优化大数据量使用 LazyForEach组件复用使用 Reusable代码质量编写单元测试使用 Hypium 框架样式管理使用 AppColors 设计令牌统一管理颜色21.2 推荐实践使用 AppColors 设计令牌统一管理颜色避免硬编码色值使用 Constants.ets 集中管理常量避免魔法数字使用 DataStore 门面模式封装数据操作统一访问入口使用 Builder 提取复用 UI 片段减少重复代码使用 BuilderParam 实现组件插槽提升组件灵活性21.3 避免的反模式避免在 build 函数中执行耗时操作这会阻塞 UI 渲染避免在 State 中存储大型对象会导致不必要的重渲染避免过度使用 Link 增加组件耦合优先使用 Prop避免在 aboutToAppear 中执行异步操作使用生命周期合理分配避免使用全局变量替代 StorageProp全局变量无法触发响应式更新提示以上最佳实践基于 xiexin 项目的实际开发经验总结建议在项目开发中遵守这些原则可以有效提升代码质量和开发效率。二十二、参考文档HarmonyOS 应用开发指南ArkUI 声明式开发范式状态管理 V1状态管理 V2高性能编程实践自定义组件
企业数字化 ERP 产品动态
相关推荐
智能体开发实战指南:从技术选型到商业化落地 1. 智能体入门指南的价值与定位 去年接触第一批智能体开发者时,我注意到一个有趣现象:超过80%的初学者会在相同的基础问题上反复碰壁。这些问题包括但不限于:如何选择开发框架?训练数据需要多少量级?模型微调的关键参数… · 2026/9/25 22:24:12
通过Python快速接入Taotoken并调用多模型完成对话 通过Python快速接入Taotoken并调用多模型完成对话
对于希望快速集成大模型能力的Python开发者而言,直接对接多个厂商的原生API往往意味着需要处理不同的SDK、认证方式和计费单元。Taotoken平台通过提供统一的OpenAI兼容API,简化了这一过程。本文将指导你… · 2026/7/29 1:08:12
长期使用Taotoken Token Plan套餐的成本节省观察 长期使用Taotoken Token Plan套餐的成本节省观察
在将大模型API集成到日常开发或业务中时,成本是一个持续性的考量因素。与完全按量计费的模式相比,预付费的套餐计划往往能带来更可预测的支出和潜在的节省。本文基于一段时间的实际使用体验,… · 2026/9/20 19:13:24
Atlas 300V 24G部署YOLO全攻略:从模型转换到推理调优 1. 先搞清楚:Atlas 300V 24G到底是不是一张“运算加速卡”服务器到货那天,我做第一件事不是急着装系统,而是先插上一块全新的计算卡。卡身上的印刷体小字写得很克制:Atlas 300V 24GB。随后我打开终端敲了一句npu-smi info… · 2026/9/25 22:24:20
AI创业者开发Agent:从架构选型到评估的实战避坑指南 1. 从一条只有标题的线索说起:AI创业者做Agent到底在做什么第一次看到"AI Frontier This AI entrepreneur is developing agent"这个标题时,我手里其实只有一句话,正文、关键词、摘要全是空的。这种"光杆标题"在信息流里… · 2026/9/25 22:24:20
SaaS 选型指南:支持考勤打卡与提成自动结算的管理系统对比 实体门店的人员管理与薪资核算,是中小商户日常运营的核心痛点。多数服务型门店员工岗位灵活,技师、销售、前台多岗位并存,业绩统计、考勤登记、提成核算依赖人工手动整理,不仅耗时费力,还容易出现数据误差、核算标准不… · 2026/9/25 22:24:13
Atlas 300V 24G推理加速卡解读与YOLO部署实战 如果把“atlas 300v 24g 是运算加速卡吗”这个问题扔到任何一个AI技术群里,十有八九会吵起来。有人说是推理卡,有人说是加速卡,还有人直接把它当显卡用,结果发现连个显示器接口都没有。我刚拿到这块卡的时候也是一脸懵,… · 2026/9/25 22:24:13
AI Agent动态协作机制演进与实战调优 1. 这不是“多个AI聊天框堆在一起”——真正理解AI Agent协作机制的演进逻辑你有没有试过让两个大模型同时帮你写一份产品需求文档?一个负责梳理用户痛点,一个负责设计功能流程,结果发现它们各自为政、互相矛盾,甚至把对方刚生成的… · 2026/9/25 22:23:40
16G显存跑通QLoRA微调Qwen2.5-7B:从原理到实战 很多朋友看到“16G 显存跑 Qwen 7B 微调”,第一反应都是“别开玩笑了”。按常规全参微调的算账方式,7B 模型光权重就要 14GB(bf16),加上梯度和 AdamW 优化器状态,40GB 都不一定够,16G 确实像天方… · 2026/9/25 22:23:40
创维E900V22D刷机全攻略:S905L3SB芯片兼容性解析与救砖实战 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 1:00:31
MQTT协议原理与Broker服务器搭建实战:从Mosquitto到EMQX /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 1:00:37