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

📅 2026/7/22 5:04:16
HarmonyOS掌上记账APP开发实践第54篇:UI 组件复用策略:从 bill_card 到 asset_card 的业务组件封装
054 — UI 组件复用策略从 bill_card 到 asset_card 的业务组件封装简介在大型应用中相同的 UI 模式往往出现在多个页面——账单列表页和账单详情页都需要展示账单卡片资产总览页和资产编辑页都需要展示资产卡片。如果每个页面各自实现一套不仅代码冗余还会导致视觉和交互的不一致。MoneyTrack 将高频 UI 模式封装为独立的 HAR 组件包如bill_card和asset_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:booleanfalse;Properror:string|nullnull;// 展示配置PropshowDate:booleantrue;PropshowCategoryIcon:booleantrue;Propcompact:booleanfalse;// 事件回调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));}}这种设计让组件调用方可以灵活控制展示状态列表页在加载数据时传入loadingtrue请求失败时传入error信息数据为空时 billItem 设为 null组件自动渲染对应状态的 UI。4. 组件预览preview配置每个组件包在preview目录下配置预览页面开发者可以在 IDE 中独立查看组件在不同状态下的表现// component_bill_card/preview/BillInfoCardPreview.etsEntryComponentstruct 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。例如传入loadingtrue时验证骨架屏出现传入空数组时验证空态占位图显示。交互测试模拟用户点击、滑动等操作验证 Event 回调是否正确触发。例如点击卡片验证onItemClick是否被调用且参数正确。截图对比使用预览功能在不同设备尺寸下截图确保组件布局在各分辨率下的表现一致。项目代码案例文件路径component_bill_card/bill_card/src/main/ets/components/BillInfoCard.ets完整代码见上文多场景配置示例。文件路径component_asset_card/src/main/ets/components/AssetCard.etsComponentexportstruct AssetCard{Propasset:AssetModel;Propcompact:booleanfalse;build(){Column(){Text(this.asset.name).fontSize(this.compact?14:16);Text(this.asset.formatBalance()).fontSize(this.compact?16:20);}}}通过这套组件复用策略相同样式的卡片在列表页和详情页保持一致新增页面时只需引用对应组件并传入 props 即可。推荐参考文档UI 组件封装指南Prop / Link 装饰器文档组件预览配置指南