HarmonyOS ArkUI 组件复用与父子组件通信
在鸿蒙ArkUI声明式开发体系中组件复用与父子组件通信是从“基础页面编写”进阶到“工程化项目开发”的核心分水岭。规范化开发通过复用机制精简代码、统一UI风格并通过组件通信实现页面数据驱动更新。一、前言为什么需要组件复用在开发电商首页、购物车、列表卡片等复杂页面时页面中存在大量重复的样式、重复的UI结构、统一的交互逻辑。如果全部手写会出现代码冗余、样式不统一、后期维护成本极高的问题。ArkUI 提供了一套完整的复用方案样式复用、UI结构复用、自定义组件复用配合父子组件数据通信机制能够实现高内聚、低耦合的前端开发模式也是企业级鸿蒙项目模块化开发的基础。二、三大复用装饰器对比与实战用法(1)Styles全局通用样式复用Styles 用于抽取多个组件通用的公共样式仅复用样式属性不复用UI结构。适用于全局统一的字体、颜色、边距、对齐等基础样式。核心特点无组件绑定、全局可调用、轻量化、仅样式复用。适用场景统一页面文本样式、统一按钮默认样式、统一卡片边距圆角。// 全局通用样式 Styles function commonText() { .fontSize(14) .fontColor(#333333) .margin(10) } Styles function cardBg() { .backgroundColor(Color.White) .borderRadius(12) .shadow(0.5, 10, Color.Gray) .padding(12) }(2)Extend专属组件样式扩展与 Styles 不同Extend绑定指定原生组件只能作用于目标组件可以扩展原生组件属性甚至绑定专属交互逻辑。核心特点组件专属、可扩展原生能力、比 Styles 功能性更强。适用场景自定义专属Text文本、专属Button按钮实现全局统一的定制化组件样式。// 专属Text组件扩展样式 Extend(Text) function titleText() { .fontSize(18) .fontWeight(FontWeight.Bold) .fontColor(#000) }(3)BuilderUI结构片段复用Builder 是 ArkUI 中复用UI结构的核心方案可以封装一段重复的组件结构支持传参、支持动态数据渲染是页面局部复用的最优解。同时搭配 BuilderParam 可以实现父组件向子组件注入自定义UI片段实现高灵活度的组件插槽效果极大提升组件的复用性和扩展性。适用场景列表卡片、通用标题栏、通用空数据页面、重复弹窗结构。// 封装通用卡片布局 Builder function GoodsCard(name: string, price: number) { Column() { Text(name).titleText() Text(¥${price}).fontColor(#f56c6c).fontSize(16) } .cardBg() .width(100%) }三、自定义组件与父子组件通信原理单纯的结构复用只能解决代码冗余问题想要实现数据驱动UI更新必须依靠组件状态通信机制。在模块化开发中页面会拆分为父组件与多个子组件数据由父组件统一管理子组件负责展示通过单向数据流实现状态统一管理。(1)核心通信装饰器Prop 单向传值Prop 用于实现父组件向子组件单向数据传递是项目中最常用的组件通信方式。父组件使用 State 定义状态变量通过传参传递给子组件的 Prop 变量。核心机制父组件数据更新 → 自动同步子组件 → 子组件UI自动刷新子组件无法修改父组件数据保证数据流单向可控避免状态混乱。(2)State 与 Prop 职责区分很多新手误区子组件定义大量 State 状态。实际工程规范中State仅用于组件内部私有状态不对外暴露Prop用于接收父组件传递的业务数据只读、可响应更新该机制保证了数据来源唯一是复杂页面状态不乱、易于维护的关键。3购物车案例子组件 GoodsItem.etsComponent export struct GoodsItem { // 接收父组件传值 Prop goodsName: string Prop goodsCount: number build() { Row() { Text(this.goodsName) Text(数量${this.goodsCount}) } .commonText() } }父组件页面使用 状态更新import { GoodsItem } from ./GoodsItem Entry Component struct Index { // 父组件唯一数据源 State name: string 鸿蒙学习手册 State count: number 1 build() { Column() { // 子组件绑定父状态 GoodsItem({ goodsName: this.name, goodsCount: this.count }) // 修改父状态子组件自动刷新 Button(增加数量) .onClick(() { this.count }) } .padding(20) } }四、总结三者复用方案各司其职样式复用统一界面、Builder 结构复用精简代码、自定义组件Prop通信实现业务解耦。掌握这套体系后已经具备开发中大型电商级复杂页面的能力摆脱新手式重复编码写出规范、简洁、可维护的鸿蒙代码。