第一篇:自定义组件基础
1.1 什么是自定义组件
自定义组件是鸿蒙ArkTS开发中的核心概念,它就像是搭积木时的一个个预制模块。想象一下,如果我们每次都要从最基础的砖块开始搭建房子,那会非常繁琐。自定义组件就是帮我们预先制作好的"房间模块",可以直接拿来使用,大大提高开发效率。
自定义组件的核心价值:
- 封装性:将复杂的UI逻辑包装成简单易用的组件
- 复用性:一次编写,多处使用,避免重复代码
- 维护性:修改组件时,所有使用该组件的地方都会自动更新
- 模块化:让代码结构更清晰,便于团队协作
在鸿蒙系统中,我们使用@Component装饰器来标识一个自定义组件。每个组件都必须实现build()方法来描述其UI结构,这就像是给组件画一张"设计图纸"。
1.2 创建第一个自定义组件
让我们从一个简单的按钮组件开始,学习如何创建自定义组件。这个按钮组件将支持不同的尺寸,并且可以自定义文本和点击事件。
设计思路:
- 定义组件的输入参数(按钮文本、尺寸、点击回调)
- 根据不同尺寸返回对应的样式配置
- 在build方法中构建UI结构
- 处理用户交互事件
@Component
export struct MyButton {
@Prop buttonText: string = '默认按钮'
@Prop buttonSize: 'small' | 'medium' | 'large' = 'medium'
@Prop onButtonClick?: () => void
private getSizeStyle() {
switch (this.buttonSize) {
case 'small':
return { width: 80, height: 32, fontSize: 12 }
case 'large':
return { width: 120, height: 48, fontSize: 18 }
default:
return { width: 100, height: 40, fontSize: 14 }
}
}
build() {
Button(this.buttonText)
.width(this.getSizeStyle().width)
.height(this.getSizeStyle().height)
.fontSize(this.getSizeStyle().fontSize)
.backgroundColor('#3B82F6')
.fontColor(Color.White)
.borderRadius(8)
.onClick(() => {
if (this.onButtonClick) {
this.onButtonClick()
}
})
}
}
1.3 组件属性传递
在鸿蒙开发中,组件之间的数据传递是通过特殊的装饰器来实现的。这些装饰器就像是组件之间的"通信协议",规定了数据如何在父子组件之间流动。
主要的属性装饰器类型:
- @Prop:单向数据流,父组件向子组件传递数据
- @State:组件内部状态,数据变化时自动刷新UI
- @Link:双向数据绑定,子组件可以修改父组件的数据
- @Provide/@Consume:跨级组件通信,适用于深层嵌套场景
让我们通过具体例子来理解这些概念:
@Prop - 父向子传递
@Prop装饰器用于接收父组件传递的数据,这是最常用的数据传递方式。就像函数的参数一样,子组件通过@Prop声明需要接收哪些数据。
下面是一个用户卡片组件的例子,它接收用户名、头像和在线状态等信息:
@Component
struct UserCard {
@Prop userName: string
@Prop avatarUrl: string
@Prop isOnline: boolean = false
build() {
Row() {
Image(this.avatarUrl)
.width(50)
.height(50)
.borderRadius(25)
Column() {
Text(this.userName)
.fontSize(16)
.fontWeight(FontWeight.Bold)
Text(this.isOnline ? '在线' : '离线')
.fontSize(12)
.fontColor(this.isOnline ? '#10B981' : '#6B7280')
}
.alignItems(HorizontalAlign.Start)
.margin({ left: 12 })
}
.padding(16)
.backgroundColor('#FFFFFF')
.borderRadius(12)
}
}
@State - 组件内部状态
@State装饰器用于管理组件内部的状态数据。当状态发生变化时,鸿蒙框架会自动重新渲染相关的UI部分。这就像是给组件装上了"自动感应器",能够实时响应数据变化。
下面是一个计数器组件,演示了如何使用@State管理内部状态:
@Component
struct Counter {
@State count: number = 0
@State isActive: boolean = false
build() {
Column() {
Text(`计数: ${this.count}`)
.fontSize(24)
.fontColor(this.isActive ? '#3B82F6' : '#374151')
Row() {
Button('-')
.onClick(() => {
this.count--
this.isActive = this.count > 0
})
Button('+')
.onClick(() => {
this.count++
this.isActive = this.count > 0
})
}
.margin({ top: 16 })
}
.justifyContent(FlexAlign.Center)
.width('100%')
.height(200)
}
}
1.4 组件使用示例
@Entry
@Component
struct HomePage {
@State userList: Array<{name: string, avatar: string, online: boolean}> = [
{ name: '张三', avatar: $r('app.media.avatar1'), online: true },
{ name: '李四', avatar: $r('app.media.avatar2'), online: false }
]
build() {
Column() {
Text('自定义组件示例')
.fontSize(20)
.fontWeight(FontWeight.Bold)
.margin({ bottom: 20 })
// 使用自定义按钮
MyButton({
buttonText: '小按钮',
buttonSize: 'small',
onButtonClick: () => {
console.log('小按钮被点击')
}
})
// 使用计数器
Counter()
// 使用用户卡片
ForEach(this.userList, (user) => {
UserCard({
userName: user.name,
avatarUrl: user.avatar,
isOnline: user.online
})
.margin({ top: 12 })
})
}
.padding(20)
.width('100%')
.height('100%')
}
}
点击查看更多内容
为 TA 点赞
评论
共同学习,写下你的评论
评论加载中...
作者其他优质文章
正在加载中
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦