尧图网站建设 尧图网络
  • 首页
  • 关于我们
  • 服务项目
  • 案例展示
  • 建站流程
  • 资讯中心
  • 联系我们
首页/资讯中心/详情

HarmonyOS掌上记账APP开发实践第28篇:自定义组件封装策略 — 从通用 Header 到业务组件的分层设计

HarmonyOS掌上记账APP开发实践第28篇:自定义组件封装策略 — 从通用 Header 到业务组件的分层设计
📅 发布时间:2026/7/17 20:22:32

自定义组件封装策略 — 从通用 Header 到业务组件的分层设计

一、引言

在大型应用中,合理的组件化设计是保证代码可维护性和复用性的基石。鸿蒙的 ArkTS 通过@ComponentV2装饰器支持自定义组件,允许开发者将页面拆分为可复用的独立模块。MoneyTrack 项目从通用基础组件(如 CommonHeader)到业务领域组件(如 AssetSummaryCard、AssetCard),构建了一套清晰的组件分层体系,实现了代码的高复用和低耦合。

二、核心知识点

2.1 @ComponentV2 与 @Component(V1) 对比

鸿蒙 ArkTS 提供了两代组件装饰器。@ComponentV2(推荐)相较于@Component(V1)在响应式和性能上有显著提升:

对比维度@ComponentV2@Component(V1)
数据装饰器@Param / @Local / @Computed@State / @Prop / @Link
响应式粒度属性级,精准触发更新对象引用级,整体替换才触发
性能表现仅更新变动的属性整个组件重建
语法简洁度不需要 .build() 内部赋初值略繁琐
推荐程度强烈推荐(新项目应使用)兼容旧项目
// @ComponentV2 写法(推荐)@ComponentV2exportstruct MyComponent{@Paramcount:number=0@LocalisVisible:boolean=truebuild(){/* ... */}}// @Component(V1) 写法(旧)@Componentexportstruct OldComponent{@Statecount:number=0@PropisVisible:boolean=truebuild(){/* ... */}}

2.2 @Param 与 @Local 的角色分配

在@ComponentV2中,数据装饰器的选择决定了属性的职责:

  • @Param:接收父组件传入的外部属性(即 props),由父组件驱动更新。子组件不应修改@Param属性。
  • @Local:组件内部管理的私有状态,仅供组件自身使用,外界不可直接赋值。
@ComponentV2exportstruct UserCard{@ParamuserName:string=''// 父组件传入,只读@ParamavatarUrl:string=''// 父组件传入,只读@LocalisExpanded:boolean=false// 组件内部状态@LocallikeCount:number=0// 组件内部状态build(){Column(){Text(this.userName).fontSize(16)if(this.isExpanded){Text('详细资料...')}}}}

分配原则:凡是从父组件传入的数据用@Param,组件自己管理的交互状态用@Local。

2.3 组件通信方式

自定义组件之间通过单向数据流进行通信:

  • 父→子:通过@Param属性传递数据
  • 子→父:通过回调函数(事件)通知父组件
// 父组件使用@ComponentV2exportstruct ParentPage{@Localitems:number[]=[1,2,3]build(){Column(){ForEach(this.items,(item:number)=>{ChildCard({value:item,onDelete:(id:number)=>{this.items=this.items.filter(v=>v!==id)}})})}}}// 子组件定义@ComponentV2exportstruct ChildCard{@Paramvalue:number=0@ParamonDelete:(id:number)=>void=()=>{}build(){Row(){Text(`${this.value}`)Button('删除').onClick(()=>this.onDelete(this.value))}}}

这种模式确保了数据从父到子单向流动,子组件通过回调通知父组件执行修改,避免了双向绑定的混乱。

2.4 组件封装的最佳粒度

组件拆分需要遵循"高内聚、低耦合"原则。MoneyTrack 的组件分为三个层次:

App(应用根节点)

TabBar(底部导航)

BillPage(账单页)

StatisticsPage(统计页)

MinePage(我的页)

CommonHeader(通用标题栏)

DailyBillGroup(每日分组)

BillCard(账单卡片)

CategoryIcon(分类图标)

ChartSummary(图表摘要)

CalendarSummary(日历摘要)

MemberCard(会员卡片)

SettingItem(设置项)

经验法则:

  1. 单一职责:一个组件只做一件事。BillCard只负责展示单条账单,不负责布局列表。
  2. 接口归一化:组件的@Param应设计为统一的 Model 类型,而非零散的基础类型。
  3. props 不可变性:子组件应只读地消费@Param,不直接修改父组件数据。

2.5 CommonHeader 完整实现

以下是 MoneyTrack 中 CommonHeader 的完整代码:

@ComponentV2exportstruct CommonHeader{@Paramtitle:string=''@ParamonBack:()=>void=()=>{}@ParamrightText:string=''@ParamonRightClick:()=>void=()=>{}@ParamisDarkMode:boolean=falsebuild(){Row(){// 左侧返回按钮Image($r('app.media.ic_back')).width(24).height(24).onClick(()=>this.onBack())// 中间标题Text(this.title).fontSize(18).fontWeight(FontWeight.Bold).fontColor(this.isDarkMode?'#FFFFFF':'#333333')Blank()// 右侧可选操作if(this.rightText.length>0){Text(this.rightText).fontSize(14).fontColor('#007AFF').onClick(()=>this.onRightClick())}}.padding({left:16,right:16,top:12,bottom:12}).width('100%').backgroundColor(this.isDarkMode?'#1A1A1A':'#FFFFFF')}}

三、项目代码案例

3.1 CommonHeader 通用标题栏

在products/entry/src/main/ets/components/CommonHeader.ets中,CommonHeader 封装了统一的导航栏。该组件在 BillDetailPage、AssetDetailPage、SettingPage 等多个页面中复用,保证了导航栏的视觉统一。

3.2 AssetSummaryCard / AssetCard 业务卡片

在资产模块中,业务卡片组件封装了资产数据展示的公共逻辑:

  • AssetSummaryCard:展示资产总览摘要(总资产、净资产等汇总指标)
  • AssetCard:展示单个资产项目名称、金额、账期信息

这些组件通过@Param接收AssetGroupModel或AssetItemModel数据对象,渲染出统一的卡片 UI。

3.3 组件定义示例

@ComponentV2exportstruct AssetCard{@ParamassetData:AssetGroupModel=newAssetGroupModel()@ParamonTap:(id:number)=>void=()=>{}build(){Column(){Text(this.assetData.name).fontSize(16).fontWeight(FontWeight.Bold)Text(`¥${this.assetData.amount.toFixed(2)}`).fontSize(24)}.gesture(TapGesture().onAction(()=>{this.onTap(this.assetData.id)})).padding(16).backgroundColor(Color.White).borderRadius(12)}}

四、最佳实践总结

  1. 优先使用 @ComponentV2:新一代装饰器性能更好、语法更简洁。
  2. @Param 与 @Local 职责分明:外部数据用@Param,内部状态用@Local。
  3. 单向数据流:父传子通过 props,子传父通过回调。
  4. 组件粒度适中:过细则文件碎片化,过粗则不可复用。
  5. 保持 props 不可变:子组件不修改传入的数据,确保数据流可预测。
  6. 接口归一化:推荐传入完整 Model 对象,而非零散字段。

五、参考文档

  • 自定义组件最佳实践
  • @ComponentV2 装饰器说明
  • @Param 装饰器

相关新闻

  • AI Agent开发中的PLAN-AND-EXECUTE模式解析与实践
  • Ubuntu手动编译Linux内核全流程指南
  • 2026超限运输检测仪品牌排行榜,广州聚杰稳居行业前列 - 品牌速递

最新新闻

  • 线性dp
  • 基准测试工具之你不知道的两三事 | 2.从一次时序数据库写入测试开始
  • KVM虚拟化技术实战:从安装配置到性能优化
  • 输送人才过万、就业成功率超行业30%,这家SAP培训平台有何过人之处?
  • SolidWorks_钣金设计19_钣金参数化设计
  • 2026年7月最新亨得利官方服务项目及价格查询|详细地址与服务电话权威信息公示 - 亨得利官方

日新闻

  • 佛山青少年训练营推荐:军博营地实力顶尖 - 秋山寄远
  • 如何快速上手PvZ2 Gardendless:免费Web版植物大战僵尸2完整指南
  • jiuwen-deepsearch核心功能详解:规划-检索-反思三合一智能工作流

周新闻

  • IX9104 PCIe5.0 高速交换芯片@ACP#完整规格 + 应用场景总结
  • Unity游戏集成Coze智能体:实现NPC智能对话与知识库联动
  • SAP EPIC 建行回单查询:从标准类CL_EPIC_EXAMPLE_CN_CCB_GHTD到Z类的5处关键修改

月新闻

  • 2026年6月公司网站搭建最新热门渠道测评:四大低成本/零代码平台对比+避坑
  • 【Linux】Linux arm 编译QT程序,出现expected “}“报错
  • 【MATLAB例程】四基站二维AOA定位与距离辅助增强对比仿真。基于角度观测和测距修正的固定目标平面定位精度分析

关于尧图

  • 公司简介
  • 团队介绍
  • 企业文化
  • 荣誉资质

服务项目

  • 定制开发
  • 电商建站
  • UI 设计
  • 运维服务

快速链接

  • 案例展示
  • 建站流程
  • 常见问题
  • 资讯中心

联系方式

  • 📍北京市朝阳区互联网产业园 A 座 10 层
  • 📞400-888-8888
  • ✉️contact@rkmt.cn
  • 🕐周一至周日 9:00-21:00

© 2024 北京尧图网络科技有限公司 版权所有 | 京 ICP 备 XXXXXXXX 号