HarmonyOS7 自定义组件实战:从 @Component 到 @Builder

发布时间:2026/7/12 10:39:46
HarmonyOS7 自定义组件实战:从 @Component 到 @Builder 文章目录前言第一层Component 抽成独立组件代码实现第二层Builder 抽成UI 片段核心代码Component 还是 Builder一张表说清进阶BuilderParam 让组件可定制完整示例常见误区小白必踩完整可运行示例可复用按钮组件代码解析写在最后前言你肯定不想把同一个按钮、同一个卡片在每个页面都抄一遍。代码抄多了改一处要改八处迟早出 bug。HarmonyOS 给了两套复用手段Component 自定义组件和Builder 构建函数。这俩不是二选一而是不同尺度上的复用。今天我把它们的用法、区别、坑点一次讲清。第一层Component 抽成独立组件最彻底的复用是把一段 UI 抽成一个带自己状态的组件。代码实现Componentstruct LikeButton{StateisLiked:booleanfalsebuild(){Button(this.isLiked?已赞 ♥:点赞 ♡).fontColor(this.isLiked?#FF4500:#666666).onClick((){this.isLiked!this.isLiked})}}讲解Component标记这是一个自定义组件struct LikeButton是组件名。State isLiked是组件内部状态点了之后翻转按钮文字和颜色跟着变。在别的页面直接用LikeButton /就能用各自有各自的状态互不影响。注意自定义组件里必须有build()函数UI 全写在它里面。这是 ArkUI 的硬性规定。第二层Builder 抽成UI 片段有时候你不需要独立状态只是想复用一段长得一样的 UI 组合比如列表里每个 item 的头部。这种用Builder更轻。核心代码EntryComponentV2struct Page{BuilderSectionHeader(title:string){Row(){Text(title).fontSize(18).fontWeight(FontWeight.Bold)Blank()Text(更多 ).fontSize(12).fontColor(#999999)}.width(100%).padding({bottom:8})}build(){Column(){this.SectionHeader(推荐歌单)this.SectionHeader(每日推荐)}}}要点Builder是个函数里面直接写 UI不像Component需要struct和build()。调用时用this.SectionHeader(推荐歌单)传参就像普通函数。它没有自己的状态数据来自外部传入。适合纯展示型复用。Component 还是 Builder一张表说清维度ComponentBuilder是否有独立状态有State 等无靠传参复用粒度大完整组件小UI 片段能否跨文件能导出通常是本文件内性能开销略大极小经验法则这段 UI 要自己记点东西比如点赞状态、展开收起用Component只是长一样的展示块用Builder。进阶BuilderParam 让组件可定制有时候父组件想往子组件里塞一段自己的 UI比如卡片的内容区。用BuilderParam。完整示例Componentstruct Card{BuilderParamcontent:()voidbuild(){Column(){Text(卡片标题).fontSize(16)this.content()// 这里插入父组件传进来的 UI}.padding(12).borderRadius(12).backgroundColor(#FFFFFF)}}// 使用Card(){Text(这是塞进卡片里的自定义内容).fontSize(14)}Card() { ... }里的大括号内容就是传给content的 UI。这种插槽机制在写通用容器组件时特别香。常见误区小白必踩误区说明自定义组件忘了build()UI 必须写在build()里这是 ArkUI 的硬性规定漏了直接报错。Component 和 Builder 混着用带独立状态用Component纯展示片段用Builder别在Builder里硬塞状态。跨文件复用忘了export抽成独立文件后struct必须export否则别的模块import不到。下面这段代码可以直接复制到 DevEco Studio 里运行。建议你边读边敲改一改文末「动手改一改」里的参数亲眼看看效果。完整可运行示例可复用按钮组件把「带图标的按钮」抽成一个自定义组件再用Builder做变体避免重复写样式。代码解析// 自定义组件 Builder 复用片段EntryComponentstruct Demo{BuilderIconBtn(icon:Resource,label:string){Row({space:6}){Image(icon).width(20).height(20)Text(label).fontSize(14)}.padding({left:16,right:16,top:8,bottom:8}).backgroundColor(#007DFF).borderRadius(20)}build(){Column({space:16}){this.IconBtn($r(app.media.startIcon),开始)this.IconBtn($r(app.media.ic_public_add),添加)}.padding(20)}}你会看到什么两个蓝底白字图标文字的圆角按钮竖向排列。两个按钮共用IconBtn这段 Builder改一处样式两个一起变。动手改一改在Builder的Row上加.onClick(() {})让按钮可点击。把backgroundColor(#007DFF)提成一个State color变量做「按下变色」效果。给IconBtn增加第三个参数bgColor: ResourceColor调用时分别传不同颜色。写在最后复用这事儿早点养成习惯受益无穷。我的实践页面里出现第二次的 UI立刻考虑抽带状态的抽Component纯展示的抽Builder。等你的项目里BuilderParam插槽用顺手了组件库的雏形就有了。别光看打开 DevEco 把LikeButton敲出来在页面放两个点一个看看另一个变不变——理解组件状态隔离就靠这一下。