HarmonyOS开发实战:笔友-CommonComponents 组件库设计哲学——聚合与拆分的权衡
前言在 ArkUI 声明式开发范式中组件复用是提升开发效率和 UI 一致性的关键手段。xiexin 将 5 个通用组件集中放在一个 146 行的CommonComponents.ets文件中这种单文件聚合的设计在小型项目中极具性价比但随着项目规模增长需要向多文件拆分演进。本文将以CommonComponents.ets为蓝本详细剖析组件库设计中的聚合 vs 拆分选择、组件的导出/引用机制、Component/Prop/BuilderParam在组件封装中的配合以及组件库随着项目规模增长的演进路线。一、CommonComponents 的整体设计1.1 文件结构xiexin 的CommonComponents.ets位于entry/src/main/ets/components/CommonComponents.ets整个文件 146 行包含 5 个组件组件行数装饰器用途AvatarComponent34ComponentProp头像显示首字母回退StatusBadge22ComponentProp信件/笔友状态标签CardContainer19ComponentBuilderParam通用卡片容器EmptyState49ComponentProp空状态占位DividerLine10ComponentProp分割线1.2 所有组件代码// entry/src/main/ets/components/CommonComponents.etsimport{AppColors}from../common/Constants;// 通用头像组件Componentexportstruct AvatarComponent{Propname:string;PropavatarSize:number48;PropfontSize:number18;privategetAvatarColor():string{constcolors:string[][#E8D5B7,#D4C4A8,#C9B896,#BFA98A,#D1C0A5,#C2B59B];lethash:number0;for(leti0;ithis.name.length;i){hashthis.name.charCodeAt(i)((hash5)-hash);}returncolors[Math.abs(hash)%colors.length];}build(){Stack(){Circle().width(this.avatarSize).height(this.avatarSize).fill(this.getAvatarColor())Text(this.name.length0?this.name.charAt(0):?).fontSize(this.fontSize).fontColor(AppColors.TEXT_PRIMARY).fontWeight(FontWeight.Medium)}.width(this.avatarSize).height(this.avatarSize)}}// 状态标签组件Componentexportstruct StatusBadge{Proptext:string;Propcolor:stringAppColors.PRIMARY;PropbgColor:stringAppColors.AMBER_LIGHT;build(){Text(this.text).fontSize(11).fontColor(this.color).backgroundColor(this.bgColor).borderRadius(10).padding({left:8,right:8,top:3,bottom:3}).fontWeight(FontWeight.Medium)}}// 通用卡片容器Componentexportstruct CardContainer{BuilderParamcontent:()void;PropcardPadding:number16;build(){Column(){this.content()}.width(100%).padding(this.cardPadding).backgroundColor(AppColors.CARD_BG).borderRadius(16).shadow({radius:8,color:#0D000000,offsetX:0,offsetY:2})}}// 空状态组件Componentexportstruct EmptyState{Proptitle:string暂无内容;Propsubtitle:string;PropshowButton:booleanfalse;PropbuttonText: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.length0){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)}}// 分割线组件Componentexportstruct DividerLine{PropmarginH:number16;build(){Divider().strokeWidth(0.5).color(AppColors.DIVIDER).margin({left:this.marginH,right:this.marginH})}}二、单文件聚合 vs 多文件拆分2.1 两种模式的对比维度单文件聚合xiexin 当前多文件拆分文件数量1 个N 个代码定位在同一文件中滚动在目录中查找文件名组件耦合可见便于发现耦合隐藏独立文件导入语句一次 import 全部每个组件独立 import适合阶段小型项目 10 组件中大型项目 10 组件2.2 导入方式的差异// 单文件聚合一次 import 全部import{AvatarComponent,StatusBadge,CardContainer,EmptyState,DividerLine}from../components/CommonComponents;// 多文件拆分每个组件独立 importimport{AvatarComponent}from../components/AvatarComponent;import{StatusBadge}from../components/StatusBadge;2.3 组件库目录结构演进// 小型项目单文件 components/CommonComponents.ets // 中型项目按类别拆分 components/ ├── AvatarComponent.ets ├── StatusBadge.ets ├── CardContainer.ets ├── EmptyState.ets └── DividerLine.ets // 大型项目按模块分组 components/ ├── avatars/ │ ├── AvatarComponent.ets │ └── GroupAvatar.ets ├── badges/ │ ├── StatusBadge.ets │ └── CountBadge.ets ├── cards/ │ ├── CardContainer.ets │ └── StatsCard.ets └── states/ └── EmptyState.ets三、Component 的导出与引用3.1 export struct 的语义Componentexportstruct AvatarComponent{Propname:string;PropavatarSize:number48;PropfontSize:number18;}3.2 在页面中引用import{AvatarComponent,StatusBadge,EmptyState}from../components/CommonComponents;BuilderLetterCard(letter:Letter){Row(){AvatarComponent({name:letter.penPalName,avatarSize:40,fontSize:16})Column({space:6}){Text(letter.penPalName).fontSize(16)StatusBadge({text:this.getStatusText(letter),color:AppColors.PRIMARY})}}}四、BuilderParam 插槽设计4.1 CardContainer 的插槽Componentexportstruct CardContainer{BuilderParamcontent:()void;PropcardPadding:number16;build(){Column(){this.content()}.width(100%).padding(this.cardPadding).backgroundColor(AppColors.CARD_BG).borderRadius(16).shadow({radius:8,color:#0D000000,offsetX:0,offsetY:2})}}五、计算属性在组件中的使用privategetAvatarColor():string{constcolors:string[][#E8D5B7,#D4C4A8,#C9B896,#BFA98A,#D1C0A5,#C2B59B];lethash:number0;for(leti0;ithis.name.length;i){hashthis.name.charCodeAt(i)((hash5)-hash);}returncolors[Math.abs(hash)%colors.length];}六、条件渲染在组件中的应用if(this.subtitle.length0){Text(this.subtitle)}if(this.showButton){Button(this.buttonText)}七、组件参数设计原则// 好的参数设计明确的默认值Propname:string;PropavatarSize:number48;PropfontSize:number18;// 可选回调函数onButtonClick?:()void;八、组件库的测试策略import{describe,it,expect}fromohos/hypium;describe(EmptyState,(){it(should display title when provided,(){constcomponentnewEmptyState();component.title测试标题;expect(component.title).toBe(测试标题);});});九、组件的扩展建议Componentexportstruct AvatarComponent{Propname:string;PropavatarUrl:string;PropavatarSize:number48;PropfontSize:number18;build(){Stack(){if(this.avatarUrl.length0){Image(this.avatarUrl).width(this.avatarSize).height(this.avatarSize).borderRadius(this.avatarSize/2)}else{Circle().width(this.avatarSize).height(this.avatarSize).fill(this.getAvatarColor())Text(this.name.charAt(0)).fontSize(this.fontSize).fontColor(AppColors.TEXT_PRIMARY)}}.width(this.avatarSize).height(this.avatarSize)}}九、组件库的版本管理策略当组件库需要版本迭代时推荐以下策略新增组件在 CommonComponents 文件中新增组件不影响现有组件修改组件修改Prop参数时考虑向后兼容性废弃组件保留旧接口添加deprecated注释/** * deprecated 请使用 NewAvatarComponent 替代 */Componentexportstruct AvatarComponent{// 旧接口}十、组件库的文档化组件库的文档化是团队协作的关键每个组件需要标注Prop参数说明提供使用示例代码标注不兼容的变更/** * 头像组件 * param name 用户名用于首字母和颜色计算 * param avatarSize 头像尺寸默认 48 * param fontSize 首字母字号默认 18 */Componentexportstruct AvatarComponent{Propname:string;PropavatarSize:number48;PropfontSize:number18;}十一、从 xiexin 看组件库设计xiexin 的组件库设计体现了够用就好的原则单文件聚合5 个组件146 行适合当前阶段Prop 参数化所有组件可通过参数定制BuilderParam 插槽CardContainer 支持内容注入可选回调EmptyState 的 onButtonClick 可选提示当组件数量超过 10 个时建议按组件类型拆分到独立文件避免单文件膨胀。十二、组件库的 CI/CD 集成在团队协作中组件库的自动化测试和发布是保证质量的关键单元测试每个组件需要有对应的ohos/hypium测试用例视觉回归测试使用截图对比工具检测 UI 变化自动发布组件库可以发布为 HAR 包供其他模块使用// oh-package.json5 { dependencies: { xiexin/common-components: 1.0.0 } }总结本文详细剖析了 xiexin 的 CommonComponents 组件库设计哲学重点讲解了单文件聚合 vs 多文件拆分的权衡、Prop 参数化设计、BuilderParam 插槽模式以及组件库随着项目规模增长的演进路线。如果这篇文章对你有帮助欢迎点赞、收藏⭐、关注你的支持是我持续创作的动力相关资源开源鸿蒙跨平台社区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-component-reusableHarmonyOS 自定义组件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 BuilderParam 装饰器https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-builderparamHarmonyOS 自定义组件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 BuilderParam 装饰器https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-builderparamHarmonyOS Prop 装饰器https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-propHarmonyOS 组件复用开发实践https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-component_reuseHarmonyOS 状态管理概述https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-state-management-overviewHarmonyOS 自定义组件生命周期https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-custom-components-lifecycle

相关新闻

动态多智能体通信拓扑优化技术与应用

动态多智能体通信拓扑优化技术与应用

1. 项目概述:自动多智能体通信拓扑设计 在分布式智能系统领域,多智能体协同作业的效率很大程度上取决于通信拓扑结构的设计。传统方法通常采用固定拓扑(如全连接、星型或环形)或基于规则的自适应机制,这些方案要么缺乏…

2026/7/25 15:32:25 阅读更多 →
从GROMACS到结合自由能:gmx_MMPBSA终极指南

从GROMACS到结合自由能:gmx_MMPBSA终极指南

从GROMACS到结合自由能:gmx_MMPBSA终极指南 【免费下载链接】gmx_MMPBSA gmx_MMPBSA is a new tool based on AMBERs MMPBSA.py aiming to perform end-state free energy calculations with GROMACS files. 项目地址: https://gitcode.com/gh_mirrors/gm/gmx_MMP…

2026/7/25 15:32:25 阅读更多 →
第39章:MongoDB 极端性能调优与容量规划

第39章:MongoDB 极端性能调优与容量规划

1. 项目背景 业务场景&#xff1a;本地生活电商准备迎接年度最大促销——“618 年中大促”。运维团队接到死命令&#xff1a;系统必须扛住 10 万 QPS 的读写混合负载&#xff0c;P99 延迟 < 100ms。目前的架构——3 分片 3 节点复制集&#xff0c;8 核 32GB 9 台服务器。…

2026/7/25 15:32:25 阅读更多 →

最新新闻

1218. 最长定差子序列

1218. 最长定差子序列

题目描述 给你一个整数数组 arrarrarr 和一个整数 differencedifferencedifference&#xff0c;请你找出并返回 arrarrarr 中最长等差子序列的长度&#xff0c;该子序列中相邻元素之间的差等于 differencedifferencedifference。 子序列 是指在不改变其余元素顺序的情况下&…

2026/7/25 15:46:33 阅读更多 →
金融风控场景下Qwen-7B大模型微调实战指南

金融风控场景下Qwen-7B大模型微调实战指南

1. 项目背景与核心价值去年开源大模型爆发式增长&#xff0c;但直接使用基础模型往往难以满足特定业务需求。我在金融风控场景中尝试直接调用Qwen-7B时发现&#xff0c;虽然通用能力不错&#xff0c;但在行业术语理解和风险规则判断上准确率只有63%。这促使我深入研究大模型微调…

2026/7/25 15:46:33 阅读更多 →
视频本地化混合翻译方案:AI与人工的黄金比例

视频本地化混合翻译方案:AI与人工的黄金比例

1. 视频本地化行业的翻译需求现状视频内容全球化传播已成为企业拓展市场的标配需求。根据行业调研数据&#xff0c;85%的跨国企业需要将核心视频内容本地化为至少5种语言。传统纯人工翻译模式面临三大痛点&#xff1a;成本高&#xff08;专业译员每分钟视频收费约15-30美元&…

2026/7/25 15:46:33 阅读更多 →
《地狱之门:东线》发电机行动战术解析:转进如风与兵种协同

《地狱之门:东线》发电机行动战术解析:转进如风与兵种协同

如果你是一名二战游戏爱好者,最近在《地狱之门:东线》的英军战役中卡关,特别是面对“发电机行动”(敦刻尔克大撤退)这个高难度任务时感到束手无策,那么这篇文章就是为你准备的。 很多玩家以为这场战役只是简单的“边打边撤”,但实际上它考验的是你对战场节奏的精准把控…

2026/7/25 15:46:33 阅读更多 →
SVGEdit快速导出指南:3种格式转换技巧与最佳实践

SVGEdit快速导出指南:3种格式转换技巧与最佳实践

SVGEdit快速导出指南&#xff1a;3种格式转换技巧与最佳实践 【免费下载链接】svgedit Powerful SVG-Editor for your browser 项目地址: https://gitcode.com/gh_mirrors/sv/svgedit SVGEdit是一款功能强大的浏览器端SVG编辑器&#xff0c;能够帮助用户轻松创建和编辑矢…

2026/7/25 15:46:33 阅读更多 →
为什么83%的HR团队部署AI离职预测后反而流失更多骨干?资深CTO拆解3个被忽视的数据信任断点

为什么83%的HR团队部署AI离职预测后反而流失更多骨干?资深CTO拆解3个被忽视的数据信任断点

更多请点击&#xff1a; https://codechina.net 第一章&#xff1a;为什么83%的HR团队部署AI离职预测后反而流失更多骨干&#xff1f;资深CTO拆解3个被忽视的数据信任断点 当AI模型将高绩效工程师标记为“高离职风险”时&#xff0c;HR立即发起挽留面谈——结果该员工在两周后…

2026/7/25 15:45:31 阅读更多 →

日新闻

突破文档下载限制:kill-doc让你看到的都能保存

突破文档下载限制:kill-doc让你看到的都能保存

突破文档下载限制&#xff1a;kill-doc让你看到的都能保存 【免费下载链接】kill-doc 看到经常有小伙伴们需要下载一些免费文档&#xff0c;但是相关网站浏览体验不好各种广告&#xff0c;各种登录验证&#xff0c;需要很多步骤才能下载文档&#xff0c;该脚本就是为了解决您的…

2026/7/25 0:00:35 阅读更多 →
C++ string类模拟实现:从深拷贝到内存管理的完整指南

C++ string类模拟实现:从深拷贝到内存管理的完整指南

1. 项目概述&#xff1a;为什么我们要“手撕”string类&#xff1f;在C的学习道路上&#xff0c;尤其是从C语言过渡到C的“初阶”阶段&#xff0c;string类绝对是一个绕不开的核心。标准库里的std::string用起来太方便了&#xff0c;、find、substr&#xff0c;几个操作符和函数…

2026/7/25 0:00:35 阅读更多 →
三角洲寻宝鼠工具:高效文件搜索与资源管理实战指南

三角洲寻宝鼠工具:高效文件搜索与资源管理实战指南

1. 先搞清楚“三角洲寻宝鼠”到底是什么工具从名称来看&#xff0c;“三角洲寻宝鼠”更像是一个资源查找或文件检索类工具&#xff0c;而不是游戏或娱乐软件。这类工具的核心价值在于帮助用户快速定位特定资源&#xff0c;比如文档、图片、压缩包或特定格式的文件。如果你经常需…

2026/7/25 0:00:35 阅读更多 →

周新闻

Go语言静态资源打包方案对比与实践指南

Go语言静态资源打包方案对比与实践指南

1. 项目背景与核心需求在Go语言开发中&#xff0c;我们经常需要处理静态资源文件的打包问题。无论是Web应用的模板文件、前端资源&#xff0c;还是配置文件、证书等&#xff0c;都需要随程序一起分发。传统做法是将这些文件与编译后的二进制文件放在同一目录下&#xff0c;但这…

2026/7/25 5:08:22 阅读更多 →
Go语言实现高性能LDAP认证服务的架构与实践

Go语言实现高性能LDAP认证服务的架构与实践

1. 项目背景与核心价值LDAP&#xff08;轻量级目录访问协议&#xff09;作为企业级身份认证的黄金标准&#xff0c;已经服务了超过80%的财富500强公司。我在金融科技领域实施统一认证体系时&#xff0c;发现传统Java方案存在启动慢、内存占用高等痛点。而Go语言凭借其协程并发模…

2026/7/25 5:13:53 阅读更多 →
【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

更多请点击&#xff1a; https://intelliparadigm.com 第一章&#xff1a;AI面试官实战指南的核心价值与适用场景 AI面试官并非替代人类HR的“黑箱工具”&#xff0c;而是以可解释、可审计、可迭代的方式&#xff0c;赋能招聘全链路的关键基础设施。其核心价值在于将主观经验沉…

2026/7/24 18:52:18 阅读更多 →

月新闻