#星计划#鸿蒙原生应用从设置页看自定义组件的使用【坚果派-坚果】 原创
鸿蒙原生应用从设置页看自定义组件的使用
作者:坚果
组织:坚果派
团队介绍:坚果派由坚果创建,团队拥有8个华为HDE,3个HSD,以及若干其他领域的三十余位万粉博主运营。
本人为华为HDE、中国计算机学会CCF专业会员、OpenHarmony布道师、开发者联盟优秀讲师、2023年开源之夏导师、2023年OpenHarmony应用创新赛导师、RISC-V+OpenHarmony应用创意赛导师、OpenHarmony三方库贡献者、开放原子开源基金会技术+生态贡献者第一批开放原子开源讲师,团队成员聚集在北京,上海,南京,深圳,广州,宁夏等地,欢迎合作
运行环境
IDE:DevEco Studio 4.0 Release Build Version: 4.0.0.600, built on October 17, 2023
SDK:4.0.10.13
开发板:DAYU200版本4.0.10.16
设置页效果
首先我们用传统的方式去实现,代码如下。
普通方式
Row() {
Image($r("app.media.hy")).width(50).margin({
left: 40, right: 20
})
Text("会员").fontSize(30).fontWeight(800)
}.width("100%").backgroundColor(Color.White)
Row() {
Image($r("app.media.yx")).width(50).margin({
left: 40, right: 20
})
Text("邮箱").fontSize(30).fontWeight(800)
}.width("100%").backgroundColor(Color.White)
Row() {
Image($r("app.media.cg")).width(50).margin({
left: 40, right: 20
})
Text("草稿").fontSize(30).fontWeight(800)
}.width("100%").backgroundColor(Color.White)
但大家也都发现了,这里面出来图标和标题不一样,布局是一样的,这样的情况下我们可以考虑用自定义组件去实现
自定义组件的三个特点
自定义组件的特点
自定义组件具有以下特点:
-
可组合:允许开发者组合使用系统组件、及其属性和方法。
-
可重用:自定义组件可以被其他组件重用,并作为不同的实例在不同的父组件或容器中使用。
-
数据驱动UI更新:通过状态变量的改变,来驱动UI的刷新。
自定义组件的基本结构
-
struct:自定义组件基于struct实现,struct + 自定义组件名 + {…}的组合构成自定义组件,不能有继承关系。对于struct的实例化,可以省略new。需要说明的是自定义组件名、类名、函数名不能和系统组件名相同。
-
@Component:@Component装饰器仅能装饰struct关键字声明的数据结构。struct被@Component装饰后具备组件化的能力,需要实现build方法描述UI,一个struct只能被一个@Component装饰。@Component可以接受一个可选的bool类型参数。
了解了自定义组件的基本结构以后,我们来实现一下设置页的自定义组件,如下代码所以。
@Component
export struct SettingComponent {
private img: Resource = $r("app.media.yx")
private title: string = ""
build() {
Row() {
Image(this.img).width(50).margin({
left: 40, right: 20
})
Text(this.title).fontSize(30).fontWeight(800)
}.width("100%").backgroundColor(Color.White)
}
}
使用办法
第一步导入
import { SettingComponent } from '../com/SettingComponent'
第二步使用
SettingComponent({
title: "会员",
img: $r("app.media.hy")
})
SettingComponent({
title: "邮箱",
img: $r("app.media.yx")
})
SettingComponent({
title: "草稿",
img: $r("app.media.cg")
})
对比上面的传统方式,自定义组件重用性更高。代码量也可以降低。
我们给自定义组件添加一个点击事件
@Component
export struct SettingComponent {
private img: Resource = $r("app.media.yx")
private title: string = ""
private itemOnClick = (event: ClickEvent) => {
} //item的单击事件(可选)
build() {
Row() {
Image(this.img).width(50).margin({
left: 40, right: 20
})
Text(this.title).fontSize(30).fontWeight(800)
Blank()
Image($r("app.media.back")).width(50)
}.width("100%").backgroundColor(Color.White).margin({
bottom: 10
}).onClick((event: ClickEvent) => {
this.itemOnClick(event)
})
}
}
使用
SettingComponent({
title: "草稿",
img: $r("app.media.cg"),
itemOnClick:()=>{
router.pushUrl({
url:"pages/Index"
})
}
})
使用之后,我们再来看一下自定义组件的生命周期
自定义组件的生命周期
aboutToAppear
aboutToAppear?(): void
aboutToAppear函数在创建自定义组件的新实例后,在执行其build()函数之前执行。允许在aboutToAppear函数中改变状态变量,更改将在后续执行build()函数中生效。
从API version 9开始,该接口支持在ArkTS卡片中使用。
aboutToDisappear
aboutToDisappear?(): void
aboutToDisappear函数在自定义组件析构销毁之前执行。不允许在aboutToDisappear函数中改变状态变量,特别是@Link变量的修改可能会导致应用程序行为不稳定。
从API version 9开始,该接口支持在ArkTS卡片中使用。
onPageShow
onPageShow?(): void
页面每次显示时触发一次,包括路由过程、应用进入前台等场景,仅@Entry装饰的自定义组件生效。
onPageHide
onPageHide?(): void
页面每次隐藏时触发一次,包括路由过程、应用进入后台等场景,仅@Entry装饰的自定义组件生效。
onBackPress
onBackPress?(): void | boolean
当用户点击返回按钮时触发,仅@Entry装饰的自定义组件生效。
参考资料
这样自定义组件的使用就完成了。
注意事项
1.自定义组件只有被导出,才可以被别的组件使用
2.自定义组件中的变量,后期不修改的话,推荐用private修饰,提高程序性能。
3.如何让自定义组件预览,我们可以加个@Preview装饰器
完整代码
定义:
@Preview
@Component
export struct SettingComponent {
private img: Resource = $r("app.media.yx")
private title: string = "标题"
private itemOnClick = (event: ClickEvent) => {
} //item的单击事件(可选)
build() {
Row() {
Image(this.img).width(50).margin({
left: 40, right: 20
})
Text(this.title).fontSize(30).fontWeight(800)
Blank()
Image($r("app.media.back")).width(50)
}.width("100%").backgroundColor(Color.White).margin({
bottom: 10
}).onClick((event: ClickEvent) => {
this.itemOnClick(event)
})
}
}
使用
import router from '@ohos.router'
import { SettingComponent } from '../com/SettingComponent'
@Entry
@Component
struct SettingPage {
@State message: string = 'Hello World'
build() {
Column() {
Row() {
Image($r("app.media.hy")).width(50).margin({
left: 40, right: 20
})
Text("会员").fontSize(30).fontWeight(800)
}.width("100%").backgroundColor(Color.White)
Row() {
Image($r("app.media.yx")).width(50).margin({
left: 40, right: 20
})
Text("邮箱").fontSize(30).fontWeight(800)
}.width("100%").backgroundColor(Color.White)
Row() {
Image($r("app.media.cg")).width(50).margin({
left: 40, right: 20
})
Text("草稿").fontSize(30).fontWeight(800)
}.width("100%").backgroundColor(Color.White)
SettingComponent({
title: "会员",
img: $r("app.media.hy")
})
SettingComponent({
title: "邮箱",
img: $r("app.media.yx")
})
Divider().color(Color.Blue).strokeWidth(7)
SettingComponent({
title: "草稿",
img: $r("app.media.cg"),
itemOnClick:()=>{
router.pushUrl({
url:"pages/Index"
})
}
})
}.width("100%").height("100%").backgroundColor(Color.Orange)
}
}
完毕。谢谢大家