HarmonyOS第五章:组件抽取、构建函数抽取@Builder、构建函数插槽@BuilderParam

[复制链接]
发表于 2026-2-10 17:22:02 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
🎉 博客主页:【剑九_六千里-CSDN博客】【剑九_六千里-掘金社区】
🎨 上一篇文章:【HarmonyOS第四章:样式操纵及渲染页面】
🎠 系列专栏:【HarmonyOS系列】
💖 感谢各人点赞👍收藏⭐批评✍
  




弁言:
在鸿蒙应用开发中,随着应用复杂度的提升,怎样有用地构造和管理代码成为了一个告急的课题。
本文将探究怎样通过组件化和构建函数的使用来优化代码布局,进步代码的可读性和可维护性。
我们将从组件化的底子开始,渐渐深入到构建函数的高级用法,包罗怎样使用 @Builder 和 @BuilderParam 来进一步增强组件的机动性和复用性。
无论你是刚打仗鸿蒙应用开发的新手还是有肯定履历的开发者,都能从中得到实用的本领和最佳实践。让我们一起探索这些强大的工具吧!
1. 组件化抽取

1.1. 组件拆分及导入导出

刚开始写鸿蒙代码时,我们的代码都是在一个文件中编写,如下:



  • 重复代码较多
  • 倒霉于维护
  1. @Entry
  2. @Component
  3. struct ComponentPage {
  4.   build() {
  5.       Column() {
  6.         Text("header")
  7.           .width("100%")
  8.           .height(200)
  9.           .backgroundColor(Color.Pink)
  10.         Text("content")
  11.           .width("100%")
  12.           .height(200)
  13.           .backgroundColor(Color.Red)
  14.         Text("footer")
  15.           .width("100%")
  16.           .height(200)
  17.           .backgroundColor(Color.Yellow)
  18.       }
  19.   }
  20. }
复制代码
当页面特殊复杂时,如许写会导致代码量太大,倒霉于后续维护,那么可以接纳下面这种方式:
创建 components/layout 文件夹:

导出每个组件:


  • Header.ets
  1. @Component
  2. export struct Header {
  3.   build() {
  4.     Text("header")
  5.       .width("100%")
  6.       .height(200)
  7.       .backgroundColor(Color.Pink)
  8.   }
  9. }
复制代码


  • Content.ets
  1. @Component
  2. export struct Content {
  3.   build() {
  4.     Text("content")
  5.       .width("100%")
  6.       .height(200)
  7.       .backgroundColor(Color.Red)
  8.   }
  9. }
复制代码


  • Footer.ets
  1. @Component
  2. export struct Footer {
  3.   build() {
  4.     Text("footer")
  5.       .width("100%")
  6.       .height(200)
  7.       .backgroundColor(Color.Yellow)
  8.   }
  9. }
复制代码
主页面导入并使用:



  • 将子组件导入父组件
  • 在负组件中直接使用子组件即可
  1. import { Header } from "../components/layout/Header";
  2. import { Content } from "../components/layout/Content";
  3. import { Footer } from "../components/layout/Footer";
  4. @Entry
  5. @Component
  6. struct ComponentPage {
  7.   build() {
  8.       Column() {
  9.         Header()
  10.         Content()
  11.         Footer()
  12.       }
  13.   }
  14. }
复制代码
固然了,在同一个文件中抽取组件也是可行的,如下:



  • 在同一文件中通过 @Component 装饰器创建子组件
  • 在父组件中引用即可
  1. @Entry
  2. @Component
  3. struct Index {
  4.   build() {
  5.     Column() {
  6.       ListModel()
  7.     }
  8.     .width("100%")
  9.     .height("100%")
  10.   }
  11. }
  12. // 同一文件中抽取组件
  13. @Component
  14. struct ListModel {
  15.   build() {
  16.     Text(`123`)
  17.       .fontSize(24)
  18.   }
  19. }
复制代码
2. 构建函数抽取

2.1. @Builder

页面抽取为组件后,组件中有一些相似的内容,又可以抽取为构建函数:



  • 将部分UI抽取为公共构建函数
  1. @Component
  2. export struct Header {
  3.   // 组件内构建函数:不需要 function 关键字声明
  4.   // 通过 this.ListModel() 调用
  5.   @Builder ListModel() {
  6.     Text(title)
  7.       .fontSize(30)
  8.       .width("100%")
  9.       .height(100)
  10.       .backgroundColor(Color.Pink)
  11.   }
  12.   build() {
  13.     Column() {
  14.       this.ListModel()
  15.     }
  16.   }
  17. }
  18. // 全局构建函数:需要 function 关键字声明
  19. // 直接 ListModel() 调用
  20. // @Builder function ListModel() {
  21. //   Text("你好")
  22. //     .fontSize(30)
  23. //     .width("100%")
  24. //     .height(100)
  25. //     .backgroundColor(Color.Pink)
  26. // }
复制代码
2.2. @Builder传参转达

1)按值转达



  • 标题通过参数转达
  • 只转达一个参数
  1. @Component
  2. export struct Header {
  3.   // 组件内构建函数:不需要 function 关键字声明
  4.   // 通过 this.ListModel() 调用
  5.   @Builder ListModel(title: string) {
  6.     Text(title)
  7.       .fontSize(30)
  8.       .width("100%")
  9.       .height(100)
  10.       .backgroundColor(Color.Pink)
  11.   }
  12.   build() {
  13.     Column() {
  14.       this.ListModel("你好")
  15.     }
  16.   }
  17. }
  18. // 全局构建函数:需要 function 关键字声明
  19. // 直接 ListModel() 调用
  20. // @Builder function ListModel(title: string) {
  21. //   Text(title)
  22. //     .fontSize(30)
  23. //     .width("100%")
  24. //     .height(100)
  25. //     .backgroundColor(Color.Pink)
  26. // }
复制代码
2)按引用转达



  • 名称总数通过参数转达
  • 可转达多个参数
  • 点击按钮增长总数
  1. interface IOptions {
  2.   name: string;
  3.   count: number;
  4. }
  5. @Component
  6. export struct Header {
  7.   @State count: number = 1;
  8.   // 组件内构建函数:不需要 function 关键字声明
  9.   // 通过 this.ListModel() 调用
  10.   @Builder ListModel(options: IOptions) {
  11.     Text(`${options.name}-------------------${options.count}`)
  12.       .width("100%")
  13.       .height(20)
  14.       .backgroundColor(Color.Pink)
  15.   }
  16.   build() {
  17.     Column() {
  18.       this.ListModel({name: "Header", count: this.count})
  19.       this.ListModel({name: "Header", count: this.count * 2})
  20.       this.ListModel({name: "Header", count: this.count * 4})
  21.       Button("增加count").onClick(() => {
  22.         this.count++;
  23.       })
  24.     }
  25.   }
  26. }
  27. // 全局构建函数:需要 function 关键字声明
  28. // 直接 ListModel() 调用
  29. // @Builder function ListModel(options: IOptions) {
  30. //   Text(`${options.name}-------------------${options.count}`)
  31. //     .width("100%")
  32. //     .height(20)
  33. //     .backgroundColor(Color.Pink)
  34. // }
复制代码
留意:


  • 在使用 @Builder 复用逻辑时,可以支持转达参数,从而实现更机动的UI渲染。
  • 参数可以是状态数据,但发起使用对象的方式举行转达(直接转达,无法实现视图更新)。
  • 可以使用 Component 来抽象组件,而 @Builder 则可以实现轻量级的UI复用。
  • 按引用转达,参数界说范例时,不能使用字面量情势,必要使用 interface 大概 type 界说。
3. 构建函数插槽 @BuilderParam

@BuilderParam 是一个装饰器,用于声明恣意 UI 形貌的一个元素,类似于 slot 占位符。
当开发者创建了自界说组件,并想对该组件添加特定功能时,比方在自界说组件中添加一个点击跳转操纵。
若直接在组件内嵌入事故方法,将会导致全部引入该自界说组件的地方均增长了该功能。
为办理此题目,ArkUI 引入了 @BuilderParam 装饰器,@BuilderParam 用来装饰指向 @Builder 方法的变量,开发者可在初始化自界说组件时对此属性举行赋值,为自界说组件增长特定的功能。
3.1. 尾随闭包初始化组件(默认插槽)




  • 组件后加 {} 誊写,称为尾随闭包
  • 组件多次使用时,如未转达插槽,需通过 @Builder 声明默认内容
  1. // @BuilderParam
  2. @Entry
  3. @Component
  4. struct Index {
  5.   build() {
  6.     Column() {
  7.       ListModel() {
  8.         // 传递默认插槽
  9.         Text("默认插槽")
  10.           .fontSize(24)
  11.       }
  12.       // 此处未使用插槽
  13.       ListModel()
  14.     }
  15.     .width("100%")
  16.     .height("100%")
  17.   }
  18. }
  19. @Component
  20. struct ListModel {
  21.   // 使用父组件的尾随闭包{}(@Builder装饰的方法)初始化子组件@BuilderParam
  22.   @BuilderParam ListModelFn: () => void = this.ListModelDefaultFn;
  23.   // 如果默认插槽未传递,则默认一个内容
  24.   @Builder ListModelDefaultFn () {
  25.     Text("这是默认内容")
  26.   }
  27.   build() {
  28.     Column() {
  29.       Text("尾随闭包")
  30.         .fontSize(24)
  31.       // 接收默认插槽
  32.       this.ListModelFn()
  33.     }
  34.   }
  35. }
复制代码
3.2. 参数初始化组件(具名插槽)




  • @BuilderParam 装饰的方法可以是有参数和无参数的两种情势,需与指向的 @Builder 方法范例匹配。
  • @BuilderParam 装饰的方法范例必要和 @Builder 方法范例同等。
  • @BuilderParam 装饰的方法必须要有默认值,要不会报错,默认值是一个函数,通过 @Builder 装饰
  1. @Entry
  2. @Component
  3. struct Index {
  4.   @Builder HeaderContent() {
  5.     Text("上部分内容")
  6.       .fontColor(Color.White)
  7.       .height(40)
  8.       .backgroundColor(Color.Blue)
  9.       .width("100%")
  10.       .textAlign(TextAlign.Center)
  11.   }
  12.   @Builder FooterContent() {
  13.     Text("下部分内容")
  14.       .fontColor(Color.White)
  15.       .height(40)
  16.       .backgroundColor(Color.Blue)
  17.       .width("100%")
  18.       .textAlign(TextAlign.Center)
  19.   }
  20.   build() {
  21.     Column({space:10}) {
  22.       ListModel({ title:"中间内容",
  23.         HeaderCon: this.HeaderContent, // 可以传递多个插槽,只传递,不调用
  24.         FooterCon: () => { this.FooterContent() } // 也可以才有箭头函数的形式传递
  25.       })
  26.     }
  27.     .width('100%')
  28.     .height('100%')
  29.   }
  30. }
  31. @Component
  32. struct ListModel {
  33.   title:string = "";
  34.   @BuilderParam HeaderCon:() => void = this.Default;
  35.   @BuilderParam FooterCon:() => void = this.Default;
  36.   // 必须要有默认值,要不会报错
  37.   @Builder Default () {
  38.     Text("")
  39.   }
  40.   build() {
  41.     Column(){
  42.       // 组件中调用
  43.       this.HeaderCon()
  44.       Text(this.title)
  45.         .width("100%")
  46.         .height(40)
  47.         .textAlign(TextAlign.Center)
  48.         .fontColor(Color.White)
  49.         .backgroundColor(Color.Red)
  50.       // 组件中调用
  51.       this.FooterCon()
  52.     }
  53.     .width("100%")
  54.   }
  55. }
复制代码
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表