HarmonyOS鸿蒙Next中如何使用@Component创建自定义组件?@Prop和@Link如何实现父子通信?
HarmonyOS鸿蒙Next中如何使用@Component创建自定义组件?@Prop和@Link如何实现父子通信? 我想在 HarmonyOS 应用中封装可复用的 UI 组件,想了解:
-
@Component 装饰器的作用是什么?组件的基本结构包括哪些部分?
-
如何通过 @Prop 接收父组件传递的属性?
-
@Link 如何实现父子组件的双向数据绑定?
-
如何使用 export 导出组件供其他文件使用?
-
组件的生命周期方法(aboutToAppear、aboutToDisappear)如何使用?
希望能获取自定义组件的完整封装示例。
更多关于HarmonyOS鸿蒙Next中如何使用@Component创建自定义组件?@Prop和@Link如何实现父子通信?的实战教程也可以访问 https://www.itying.com/category-93-b0.html
实现思路:
- 使用 @Component 装饰器定义自定义组件,使用 @Prop 接收父组件传递的属性(单向):
[@Component](/user/Component)
export struct GlassCard {
[@Prop](/user/Prop) title: string = '';
[@Prop](/user/Prop) subtitle: string = '';
build() {
Column() {
Text(this.title).fontSize(16).fontWeight(FontWeight.Bold)
Text(this.subtitle).fontSize(12).fontColor('#666')
}
.padding(16)
.backgroundColor('#FFFFFF')
.borderRadius(12)
}
}
- 使用 @Link 实现父子组件双向数据绑定,子组件修改会同步到父组件:
[@Component](/user/Component)
export struct ToggleCard {
[@Prop](/user/Prop) title: string = '';
[@Link](/user/Link) isOn: boolean; // 双向绑定
build() {
Row() {
Text(this.title)
Blank()
Toggle({ type: ToggleType.Switch, isOn: this.isOn })
.onChange((value: boolean) => this.isOn = value)
}
.width('100%')
.padding(16)
}
}
@Entry
[@Component](/user/Component)
struct ParentPage {
@State switchOn: boolean = false;
build() {
Column({ space: 16 }) {
// [@Prop](/user/Prop):直接传值
GlassCard({ title: '标题', subtitle: '副标题' })
// [@Link](/user/Link):使用 $ 前缀
ToggleCard({ title: '开关设置', isOn: $switchOn })
Text(`当前状态: ${this.switchOn}`)
}
.padding(16)
}
}
- 完整示例代码:
// components/GlassCard.ets
[@Component](/user/Component)
export struct GlassCard {
[@Prop](/user/Prop) title: string = '';
[@Prop](/user/Prop) subtitle: string = '';
[@Prop](/user/Prop) icon: Resource | null = null;
[@Link](/user/Link) isExpanded: boolean;
@BuilderParam content: () => void = this.defaultContent;
@Builder defaultContent() {
Text('默认内容')
}
build() {
Column({ space: 8 }) {
Row() {
if (this.icon) {
Image(this.icon).width(24).height(24)
}
Column() {
Text(this.title).fontSize(16).fontWeight(FontWeight.Bold)
if (this.subtitle) {
Text(this.subtitle).fontSize(12).fontColor('#666')
}
}
.alignItems(HorizontalAlign.Start)
Blank()
Image($r('app.media.arrow'))
.width(16)
.rotate({ angle: this.isExpanded ? 90 : 0 })
}
.width('100%')
.onClick(() => this.isExpanded = !this.isExpanded)
if (this.isExpanded) {
this.content()
}
}
.padding(16)
.backgroundColor('#FFFFFF')
.borderRadius(12)
}
}
// pages/MainPage.ets
@Entry
[@Component](/user/Component)
struct MainPage {
@State cardExpanded: boolean = false;
build() {
Column({ space: 16 }) {
GlassCard({
title: '卡片标题',
subtitle: '点击展开',
isExpanded: $cardExpanded
}) {
Column({ space: 8 }) {
Text('展开的内容第一行')
Text('展开的内容第二行')
Button('操作按钮')
}
}
}
.padding(16)
}
}
更多关于HarmonyOS鸿蒙Next中如何使用@Component创建自定义组件?@Prop和@Link如何实现父子通信?的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
在HarmonyOS Next中,使用@Component装饰器创建自定义组件。示例:@Component struct MyComponent { ... }。
@Prop用于父组件向子组件传递单向数据,子组件修改不会影响父组件。@Link实现双向数据绑定,父子组件数据同步更新。
在父组件中使用时,用@State装饰变量,子组件中用@Prop或@Link接收。
在HarmonyOS Next中,使用[@Component](/user/Component)创建自定义组件并实现通信,是构建模块化UI的核心。以下是针对你问题的解答:
1. @Component装饰器与组件结构
[@Component](/user/Component)装饰器用于标记一个自定义组件,使其具备独立的UI、状态和生命周期。基本结构包括:
- 装饰器:
[@Component](/user/Component) - 结构体:包含组件状态变量(
@State,[@Prop](/user/Prop),[@Link](/user/Link)等)和UI描述(build()方法) - build()方法:必需,用于描述UI布局
示例结构:
[@Component](/user/Component)
struct MyComponent {
// 状态变量
@State message: string = 'Hello'
// UI描述
build() {
// 返回UI组件树
}
}
2. @Prop:单向属性传递
[@Prop](/user/Prop)用于接收父组件传递的只读数据,实现单向同步:
- 父组件修改数据会同步到子组件
- 子组件不能直接修改
[@Prop](/user/Prop)变量(修改不会同步回父组件)
示例:
// 子组件
[@Component](/user/Component)
struct ChildComponent {
[@Prop](/user/Prop) title: string // 接收父组件传递的title
build() {
Text(this.title)
}
}
// 父组件
@Entry
[@Component](/user/Component)
struct ParentComponent {
@State parentTitle: string = '父组件标题'
build() {
Column() {
// 传递数据给子组件
ChildComponent({ title: this.parentTitle })
}
}
}
3. @Link:双向数据绑定
[@Link](/user/Link)建立父子组件间的双向同步:
- 父组件和子组件共享同一数据源
- 任何一方的修改都会同步到另一方
示例:
// 子组件
[@Component](/user/Component)
struct ChildComponent {
[@Link](/user/Link) @Watch('onCountChange') count: number // 双向绑定
onCountChange() {
console.log('count changed:', this.count)
}
build() {
Button('子组件+1')
.onClick(() => {
this.count++ // 修改会同步到父组件
})
}
}
// 父组件
@Entry
[@Component](/user/Component)
struct ParentComponent {
@State count: number = 0
build() {
Column() {
Text(`父组件count: ${this.count}`)
ChildComponent({ count: $count }) // 使用$符号建立双向绑定
}
}
}
4. 导出组件
使用export关键字导出组件,使其可在其他文件中导入使用:
// MyComponent.ets
[@Component](/user/Component)
export struct MyComponent { // 添加export
[@Prop](/user/Prop) message: string
build() {
Text(this.message)
}
}
// 在其他文件中导入
import { MyComponent } from './MyComponent'
@Entry
[@Component](/user/Component)
struct MainPage {
build() {
MyComponent({ message: '导入的组件' })
}
}
5. 生命周期方法
- aboutToAppear():组件即将出现时调用,用于初始化操作
- aboutToDisappear():组件即将销毁时调用,用于清理资源
示例:
[@Component](/user/Component)
struct LifecycleComponent {
@State data: string = ''
aboutToAppear() {
// 组件显示前初始化
this.data = '初始化数据'
console.log('组件即将显示')
}
aboutToDisappear() {
// 组件销毁前清理
console.log('组件即将销毁')
}
build() {
Text(this.data)
}
}
完整示例:封装计数器组件
// CounterComponent.ets
[@Component](/user/Component)
export struct CounterComponent {
[@Link](/user/Link) value: number // 双向绑定计数器值
[@Prop](/user/Prop) label: string = '计数器' // 单向接收标签
aboutToAppear() {
console.log('计数器组件初始化')
}
build() {
Column() {
Text(`${this.label}: ${this.value}`)
.fontSize(20)
Row() {
Button('-')
.onClick(() => this.value--)
Button('+')
.onClick(() => this.value++)
}
}
}
}
// 使用组件
@Entry
[@Component](/user/Component)
struct MainPage {
@State count: number = 0
build() {
Column() {
CounterComponent({
value: $count, // 双向绑定
label: '点击计数' // 单向传递
})
}
}
}
关键点总结
[@Component](/user/Component)定义可复用UI单元,必须包含build()方法[@Prop](/user/Prop)实现父到子的单向数据流,适合展示型组件[@Link](/user/Link)实现父子双向同步,适合交互型组件export使组件可跨文件复用- 生命周期方法用于资源管理,注意
aboutToAppear中避免耗时操作
这种组件化模式支持高内聚、低耦合的UI开发,通过组合[@Prop](/user/Prop)和[@Link](/user/Link)可以灵活处理各种父子通信场景。

