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

HarmonyOS7 自定义组件封装:从重复代码到优雅复用只需要3步

HarmonyOS7 自定义组件封装:从重复代码到优雅复用只需要3步
📅 发布时间:2026/7/21 7:22:14

文章目录

      • 前言
      • 重复代码的痛
      • 3 步封装法
        • 第一步:提取结构
        • 第二步:定义接口
        • 第三步:完善逻辑
      • 使用封装好的 Card 组件
      • 组件设计原则
      • 写在最后

前言

上个月接手一个项目,打开代码一看——5 个页面,每个页面都有一段几乎一样的卡片 UI 代码,复制粘贴改改文字就完事。改需求的时候更惨,5 个地方都得改一遍,漏改一个就 bug。

重复代码是技术债的起点,而组件封装就是还债最快的方式。

这篇文章分享我总结的 3 步封装法,再通过一个完整的 Card 组件实战,带你从重复代码走到优雅复用。

重复代码的痛

重复代码不只是"看着不爽"的问题,它有三重罪:

  1. 改一处漏一处—— 5 个地方一样的代码,改需求只改了 4 个,第 5 个就是 bug

  1. 代码膨胀—— 本来 200 行能搞定的事,写了 800 行
  2. 不敢重构—— 重复代码太多,牵一发动全身,谁都不敢动

说白了,不封装 = 每次改动都是定时炸弹。

3 步封装法

第一步:提取结构

把重复的 UI 结构抽出来,做成独立的@Component。

封装前:每个页面直接写卡片结构

// 页面AColumn(){Image($r('app.media.pic1')).width(60).height(60).borderRadius(8)Text('标题A').fontSize(16).fontWeight(FontWeight.Bold)Text('描述A').fontSize(13).fontColor('#999')}.padding(16).backgroundColor('#fff').borderRadius(12)

封装后:抽成一个组件,结构固定

@Componentstruct Card{build(){Column(){Image($r('app.media.pic1')).width(60).height(60).borderRadius(8)Text('标题A').fontSize(16).fontWeight(FontWeight.Bold)Text('描述A').fontSize(13).fontColor('#999')}.padding(16).backgroundColor('#fff').borderRadius(12)}}

这一步只是"搬了个家",数据还是写死的。但已经有价值了——改结构只改一处。

第二步:定义接口

把写死的数据改成参数,让组件可配置。这就是组件的"接口"。

改造后:

@Componentstruct Card{@Propicon:Resource=$r('app.media.default')@Proptitle:string=''@Propdesc:string=''build(){Column(){Image(this.icon).width(60).height(60).borderRadius(8)Text(this.title).fontSize(16).fontWeight(FontWeight.Bold)Text(this.desc).fontSize(13).fontColor('#999')}.padding(16).backgroundColor('#fff').borderRadius(12)}}

关键代码讲解:

  • @Prop icon: Resource—— 图片用Resource类型,兼容$r()和网络图片
  • @Prop title: string = ''—— 默认值设为空串,避免不传参时显示 undefined
  • 用@Prop而不是@State,因为数据来自父组件,组件内部不需要拥有

这一步之后,组件就活了——传不同的参数,展示不同的内容。

第三步:完善逻辑

加入事件回调、条件渲染、样式定制等能力,让组件真正通用。

最终版本:

@Componentstruct Card{@Propicon:Resource=$r('app.media.default')@Proptitle:string=''@Propdesc:string=''@PropshowArrow:boolean=trueonCardClick?:()=>voidbuild(){Row(){Image(this.icon).width(48).height(48).borderRadius(8).objectFit(ImageFit.Cover)Column(){Text(this.title).fontSize(16).fontWeight(FontWeight.Bold).maxLines(1).textOverflow({overflow:TextOverflow.Ellipsis})Text(this.desc).fontSize(13).fontColor('#999').margin({top:4}).maxLines(2).textOverflow({overflow:TextOverflow.Ellipsis})}.layoutWeight(1).alignItems(HorizontalAlign.Start).margin({left:12})if(this.showArrow){Image($r('sys.media.ohos_ic_public_arrow_right')).width(16).height(16).fillColor('#ccc')}}.width('100%').padding(16).backgroundColor('#fff').borderRadius(12).onClick(()=>{if(this.onCardClick){this.onCardClick()}})}}

逐行讲解关键逻辑:

  • layoutWeight(1)—— 中间文字区域占满剩余空间,图标和箭头固定大小
  • maxLines(1)+textOverflow—— 标题超长时显示省略号,不会撑爆布局
  • if (this.showArrow)—— 条件渲染,不需要箭头的场景传showArrow: false
  • onCardClick?: () => void—— 可选回调,点击卡片时通知父组件
  • onClick里的空值检查—— 回调是可选的,不传就不触发,避免运行时崩溃

使用封装好的 Card 组件

对比一下,封装前 vs 封装后:

封装前(页面里重复写):

// 页面A、页面B、页面C... 每个都写一坨Row(){Image(...).width(48).height(48)Column(){Text(...);Text(...)}Image(箭头).width(16)}.padding(16).borderRadius(12).onClick(...)

封装后(一行搞定):

Card({icon:$r('app.media.settings'),title:'设置',desc:'应用设置与偏好',onCardClick:()=>{this.routerTo('Settings')}})

代码量从 10+ 行变成 1 行,改样式只改组件本身。这就是封装的价值。

组件设计原则

封装组件不是越多越好,记住这几条:

  • 两次重复就可以考虑封装—— 别等到第五次,第二次就该动手
  • 接口要少而精—— 一个组件超过 8 个参数就该拆了
  • 提供合理默认值—— 让最常用的场景可以少传参
  • 回调用可选属性——onXxx?: () => void,不传不报错
  • 样式也能参数化—— 不只是数据,圆角大小、内边距这些也可以暴露
  • 别过度封装—— 只出现一次的 UI 不用抽组件,强行封装反而增加理解成本

写在最后

组件封装这件事,说白了就是用一次的时间投入,换以后每次的省心。

3 步封装法——提取结构、定义接口、完善逻辑——听起来简单,但很多人卡在第一步就不愿意动了。毕竟复制粘贴是最快的,封装要动脑子。

但相信我,下次需求变更的时候,你会感谢今天花 10 分钟封装的自己。

相关新闻

  • AI工程师必写的三份Terraform文件:main.tf、variables.tf、outputs.tf
  • 保山市龙陵县2026最新黄金回收门店及联系方式指南 黄金回收白银回收铂金回收店铺TOP5排行榜 - 盛世金银回收
  • GitHub顶级AI贡献者:技术风向标与实战指南

最新新闻

  • 大庆律所怎么选?AI时代全新选型标准,正规靠谱律所盘点 - 资讯速览
  • Intel RealSense深度视觉SDK:从硬件感知到三维世界的智能桥梁
  • Alfred-Convert高级用法:快捷键、批量转换与工作流优化
  • OpenRun与传统部署工具对比:为什么选择代码优先的内部工具平台?[特殊字符]
  • 如何快速上手sing-geosite?从安装到配置的完整教程
  • GameVault部署与维护指南:生产环境配置、备份与升级最佳实践

日新闻

  • Python开发内部工具:7大核心库实战解析
  • 合肥雷达官方2026年7月最新信息:客户服务网点地址与售后热线权威公示 - 亨得利官方服务中心
  • PCA实战指南:从变量纠缠诊断到主成分业务解读

周新闻

  • SaaS软件行业GEO实践:AI搜索时代的品牌可见性与获客新路径
  • 什么是PCTFE?医药高端包装的“防潮王牌“材料
  • 【JVM调优实战】16-可视化利器-JConsole-VisualVM-JMC

月新闻

  • 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 号