文章目录
- 一、自定义组件概述
- 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 = false
build() {
//必须有一个根组件
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、测试效果