文章目录
- 一、自定义组件概述
- 1、什么是自定义组件
- 2、自定义组件的优点
- 二、创建自定义组件
- 1、自定义组件的结构
- 2、自定义组件要点
- 3、成员变量的创建
- 4、参数传递规则
- 三、练习案例
一、自定义组件概述
1、什么是自定义组件
在ArkUI中,UI显示的内容均为组件,由框架直接提供的称为系统组件,由开发者定义的称为自定义组件。在进行 UI 界面开发时,通常不是简单的将系统组件进行组合使用,而是需要考虑代码可复用性、业务逻辑与UI分离,后续版本演进等因素。因此,将UI和部分业务逻辑封装成自定义组件是不可或缺的能力。
2、自定义组件的优点
自定义组件具有以下优点:
- 可组合:允许开发者组合使用系统组件、及其属性和方法。
- 可重用:自定义组件可以被其他组件重用,并作为不同的实例在不同的父组件或容器中使用。
- 数据驱动UI更新:通过状态变量的改变,来驱动UI的刷新。
二、创建自定义组件
1、自定义组件的结构
- struct:自定义组件基于struct实现,struct + 自定义组件名 + {…}的组合构成自定义组件,不能有继承关系。对于struct的实例化,可以省略new。
说明:自定义组件名、类名、函数名不能和系统组件名相同。 - @Component:@Component装饰器仅能装饰struct关键字声明的数据结构。struct被@Component装饰后具备组件化的能力,需要实现build方法描述UI,一个struct只能被一个@Component装饰。
2、自定义组件要点
1、组件必须使用@Component进行装饰
2、只在页面上呈现@Entry装饰的组件,且@Entry必须唯一;其build()函数下的根节点唯一且必要,可以为非容器组件,其中ForEach禁止作为根节点。
3、build()函数下的根节点唯一且必要,且必须为容器组件,其中ForEach禁止作为根节点。
4、被@Entry 装饰的入口组件,build()函数中必须有且仅有一个根容器组件,如row()
5、自定义组件可以使用成员变量,即可以传递参数(注意:在组件内的变量都是私有化的)
6、组件传递参数时使用键值对进行传递
3、成员变量的创建
自定义组件除了必须要实现build()函数外,还可以实现其他成员函数,成员函数具有以下约束:
- 不支持静态函数。
- 成员函数的访问是私有的。
自定义组件可以包含成员变量,成员变量具有以下约束: - 不支持静态成员变量。
- 所有成员变量都是私有的,变量的访问规则与成员函数的访问规则相同。
- 自定义组件的成员变量本地初始化有些是可选的,有些是必选的。具体是否需要本地初始化,是否需要从父组件通过参数传递初始化子组件的成员变量,请参见官方文档:状态管理概述。
4、参数传递规则
自定义构建函数的参数传递有按值传递和按引用传递两种,均需遵守以下规则:
- 参数的类型必须与参数声明的类型一致,不允许undefined、null和返回undefined、null的表达式。
- 在自定义构建函数内部,不允许改变参数值。如果需要改变参数值,且同步回调用点,建议使用@Link。
- @Builder内UI语法遵循官方文档:自定义组件语法规则。
三、练习案例
1、练习需求
用自定义组件传参的方式传入4行《赤壁赋》的句子,每一行使用一个图标加上句子的排版。事件效果为,点击某一行句子,图标发生变化,且该行句子会被标记删除线。
2、练习源码
@Entry
@Component
struct Index {@State message: string = '赤壁赋'build() {Row() {Column({space:20}) {Text(this.message).fontSize(50).fontWeight(FontWeight.Bold)// Row(){// Image($r('app.media.icon'))// .width(40)// .margin(15)// Text("惟江上之清风")// .fontSize(40)// .fontColor(Color.Blue)// }// .borderRadius(25)// .backgroundColor(Color.Orange)// .padding(5)itemCom({ss:'惟江上之清风,'})itemCom({ss:'与山间之明月。'})itemCom({ss:'耳得之而为声,'})itemCom({ss:'目遇之而成色。'})}.width('100%')}.height('100%')}
}@Component
struct itemCom{private ss: string = 'Chi Bi Fu'//可以驱动UI进行更新的装饰器@State,默认设置不更新@State st: boolean = falsebuild() {//必须有一个根组件Row(){//使用单元运算符表达式判断状态值Image(this.st ? $r('app.media.ic') : $r('app.media.icon')).width(40).margin(15)//更改文本效果,当点击过后,则在文字上加一条删除线Text(this.ss).fontSize(35).fontColor(Color.Blue).decoration({type: this.st ? TextDecorationType.LineThrough : TextDecorationType.None})}.borderRadius(25).backgroundColor(Color.Orange).padding(5)//在row下设置点击事件,当点击某条句子时,就更新图标.onClick(()=>{//通过取反,使得两种图标可以交互更新this.st = !this.st})}
}
3、测试效果