当前位置: 首页 > news >正文

HarmonyOS掌上记账APP开发实践第54篇:UI 组件复用策略:从 bill_card 到 asset_card 的业务组件封装

054 — UI 组件复用策略:从 bill_card 到 asset_card 的业务组件封装

简介

在大型应用中,相同的 UI 模式往往出现在多个页面——账单列表页和账单详情页都需要展示账单卡片,资产总览页和资产编辑页都需要展示资产卡片。如果每个页面各自实现一套,不仅代码冗余,还会导致视觉和交互的不一致。MoneyTrack 将高频 UI 模式封装为独立的 HAR 组件包,如bill_cardasset_card,通过清晰的 props/events 接口定义实现复用。每个组件包还附带 README 使用文档和组件预览(preview)配置,让其他开发者可以快速上手。

核心知识点

1. 组件复用架构

组件复用架构的核心在于分层抽象,通过 mermaid 图可以清晰展示:

渲染错误:Mermaid 渲染失败: Parse error on line 9: ...graph "组件层" C1[BillInfoCard
... ----------------------^ Expecting 'SEMI', 'NEWLINE', 'SPACE', 'EOF', 'subgraph', 'end', 'acc_title', 'acc_descr', 'acc_descr_multiline_value', 'AMP', 'COLON', 'STYLE', 'LINKSTYLE', 'CLASSDEF', 'CLASS', 'CLICK', 'DOWN', 'DEFAULT', 'NUM', 'COMMA', 'NODE_STRING', 'BRKT', 'MINUS', 'MULT', 'UNICODE_TEXT', 'direction_tb', 'direction_bt', 'direction_rl', 'direction_lr', 'direction_td', got 'LINK_ID'

组件层引用领域层的数据类型,消费层通过传入 @Prop 数据和控制 @Event 回调来使用组件。组件不关心数据的来源(网络/本地/状态管理),只负责渲染和交互反馈,实现了关注点分离。

2. props/events 接口定义

  • @Prop:父组件传入的数据,支持单向数据流。
  • @Link:双向绑定的数据传递。
  • @Event(回调函数):子组件向父组件传递事件。

3. @Prop 多场景配置

一个成熟的组件需要覆盖多种使用场景——加载态、空态、错误态:

@Componentexportstruct BillInfoCard{// 数据属性@PropbillItem:BillModel|null;@Proploading:boolean=false;@Properror:string|null=null;// 展示配置@PropshowDate:boolean=true;@PropshowCategoryIcon:boolean=true;@Propcompact:boolean=false;// 事件回调onItemClick?:(id:string)=>void;onRetry?:()=>void;build(){Column(){if(this.loading){// 加载态:显示骨架屏LoadingSkeleton();}elseif(this.error){// 错误态:显示错误提示和重试按钮ErrorState({message:this.error,onRetry:this.onRetry});}elseif(!this.billItem){// 空态:显示占位提示EmptyState({message:'暂无账单数据'});}else{// 正常展示this.renderContent();}}}@BuilderrenderContent(){Row(){if(this.showCategoryIcon){CategoryIcon(this.billItem!.categoryId);}Column(){Text(this.billItem!.categoryName).fontSize(this.compact?14:16);if(this.showDate){Text(this.billItem!.date).fontSize(12);}}Text(this.billItem!.formatAmount()).fontSize(this.compact?16:20);}.onClick(()=>this.onItemClick?.(this.billItem!.id));}}

这种设计让组件调用方可以灵活控制展示状态:列表页在加载数据时传入loading=true,请求失败时传入error信息,数据为空时 billItem 设为 null,组件自动渲染对应状态的 UI。

4. 组件预览(preview)配置

每个组件包在preview目录下配置预览页面,开发者可以在 IDE 中独立查看组件在不同状态下的表现:

// component_bill_card/preview/BillInfoCardPreview.ets@Entry@Componentstruct BillInfoCardPreview{build(){Scroll(){Column({space:16}){// 正常状态预览BillInfoCard({billItem:mockBillItem,showDate:true})// 加载态预览BillInfoCard({loading:true})// 空态预览BillInfoCard({billItem:null})// 异常态预览BillInfoCard({error:'网络异常,请重试',onRetry:()=>{/* 模拟重试 */}})}.padding(16)}}}

5. 组件文档化

每个组件包附带 README 文档,说明组件的使用方式:

# @moneytrack/bill-card ## 安装 \`\`\` ohpm install @moneytrack/bill-card \`\`\` ## Props | 属性名 | 类型 | 必填 | 默认值 | 说明 | |--------|------|------|--------|------| | billItem | BillModel | 否 | null | 账单数据,为null显示空态 | | loading | boolean | 否 | false | 是否显示加载态 | | error | string | 否 | null | 错误信息,不为null显示错误态 | | showDate | boolean | 否 | true | 是否显示日期 | | compact | boolean | 否 | false | 是否启用紧凑模式 | ## Events | 事件名 | 参数类型 | 说明 | |--------|----------|------| | onItemClick | (id: string) => void | 点击卡片时触发 | | onRetry | () => void | 错误态点击重试时触发 |

6. 组件测试的基本思路

组件测试遵循"渲染测试 + 交互测试"两条主线:

  • 渲染测试:传入不同的 @Prop 组合,验证组件正确渲染对应的 UI。例如传入loading=true时验证骨架屏出现,传入空数组时验证空态占位图显示。
  • 交互测试:模拟用户点击、滑动等操作,验证 @Event 回调是否正确触发。例如点击卡片验证onItemClick是否被调用且参数正确。
  • 截图对比:使用预览功能在不同设备尺寸下截图,确保组件布局在各分辨率下的表现一致。

项目代码案例

文件路径component_bill_card/bill_card/src/main/ets/components/BillInfoCard.ets

完整代码见上文多场景配置示例。

文件路径component_asset_card/src/main/ets/components/AssetCard.ets

@Componentexportstruct AssetCard{@Propasset:AssetModel;@Propcompact:boolean=false;build(){Column(){Text(this.asset.name).fontSize(this.compact?14:16);Text(this.asset.formatBalance()).fontSize(this.compact?16:20);}}}

通过这套组件复用策略,相同样式的卡片在列表页和详情页保持一致,新增页面时只需引用对应组件并传入 props 即可。

推荐参考文档

  • UI 组件封装指南
  • @Prop / @Link 装饰器文档
  • 组件预览配置指南
http://www.jsqmd.com/news/1232038/

相关文章:

  • 电脑中毒排查与恢复:从免费软件下载到系统安全防护
  • 2026 年 7 月新发布:胶南优秀的直埋保温管厂家推荐几家,穿透冰雪!直埋保温管如何终结冬季电费? - 行业推荐官[官方】--
  • 2026年青岛啤酒节住宿攻略:如何挑选靠谱便捷的酒店 - 品牌鉴赏官2026
  • 民国足球运动员的抗战历程与技能转化
  • Robot Framework自动化测试环境搭建:从Python安装到实战项目
  • LangChain与LangGraph核心差异及多Agent系统设计
  • STM32与FreeRTOS任务管理实战指南
  • 免费游戏下载安全防护指南:从病毒查杀到系统防护
  • 旧手机改造无线网卡:低成本高性能网络方案
  • 3分钟搞定微信QQ防撤回:Windows平台终极消息保护指南
  • 单片机开发进阶:从调库到寄存器级编程
  • STM32 ADC与DMA协同工作原理解析及优化技巧
  • Mac跑视觉大模型不再玄学:MLX框架与统一内存实战指南
  • 2026 年现阶段,花莲有实力的铸铁闸门平台选型指南,别再用普通门了,它如何颠覆你的安全观? - 品质体验官
  • 2026年7月大连实木全屋定制设计/大连大平层实木全屋定制工厂排行榜_大连茗意智能家居有限公司 - 行业平台推荐
  • STM32开发入门指南:从环境搭建到LED控制
  • 劳力士官方服务项目及价格查询|全新地址及客服热线权威信息声明(2026年7月最新) - 劳力士官方服务中心
  • 跨平台C++开发实战:19条核心经验与最佳实践
  • 14代酷睿i5-14400F处理器性能解析与优化指南
  • SkyClaw-v1.0 Agent技术解析与应用实践
  • STM32F103到ACM32F403的U盘程序移植实战
  • K4A4G165WF-BCWE在网络设备与消费电子中的DDR4应用解析
  • iPhone 18 Pro通信芯片技术解析与5G频段选择
  • AI助手垂直化趋势:Marvis办公场景技术解析
  • Python库大全:从数据处理到Web开发的精选指南
  • 2026甄选:重庆大件运输物流公司品牌实力深度解析——专注重型设备与超限货物特种运输 - 甄选服务推荐
  • 高考志愿填报8大关键细节与避坑指南
  • Rust编程入门:从所有权系统到内存安全实践
  • 维生素B12缺乏与精神障碍:诊断与治疗指南
  • 苹果自研C2芯片技术解析与5G基带发展