装饰器概述
装饰器 | 说明 | 使用场景 |
---|---|---|
@Prop | 单向同步 | 父子组件间单向数据传递 |
@Link | 双向同步 | 父子组件间双向数据同步 |
@Provide/@Consume | 跨层级数据同步 | 祖先和后代组件间数据同步 |
@Observed | 类装饰器 | 使类具备响应式能力 |
@ObjectLink | 对象属性同步 | 与@Observed配合实现对象属性同步 |
完整示例演示
import { BusinessError } from '@ohos.base';
// 定义一个被@Observed装饰的类
@Observed
class User {
name: string;
age: number;
constructor(name: string, age: number) {
this.name = name;
this.age = age;
}
}
@Entry
@Component
struct MainPage {
@State message: string = 'Hello HarmonyOS';
@State count: number = 0;
@State isActive: boolean = true;
@State user: User = new User('张三', 25);
@Provide totalScore: number = 100;
build() {
Column({ space: 20 }) {
Text(this.message)
.fontSize(30)
.fontWeight(FontWeight.Bold)
Divider()
// 显示当前计数
Text(`计数: ${this.count}`)
.fontSize(20)
// 显示用户信息
Text(`用户: ${this.user.name}, 年龄: ${this.user.age}`)
.fontSize(20)
// 显示总分
Text(`总分: ${this.totalScore}`)
.fontSize(20)
.margin({ top: 10 })
Divider()
// 使用@Prop的子组件
PropChildComponent({ propMessage: this.message })
.margin({ top: 10 })
// 使用@Link的子组件
LinkChildComponent({ linkCount: $count })
.margin({ top: 10 })
// 使用@ObjectLink的子组件
ObjectLinkChildComponent({ objectLinkUser: this.user })
.margin({ top: 10 })
// 使用@Consume的子组件
ConsumeChildComponent()
.margin({ top: 10 })
Button('父组件修改数据')
.width('80%')
.onClick(() => {
this.count++;
this.user.age++;
this.totalScore += 10;
this.message = `父组件修改于 ${new Date().toLocaleTimeString()}`;
})
}
.width('100%')
.height('100%')
.padding(20)
}
}
// 使用@Prop的子组件
@Component
struct PropChildComponent {
@Prop propMessage: string;
build() {
Column() {
Text('@Prop子组件')
.fontSize(18)
.fontColor(Color.Blue)
Text(this.propMessage)
.fontSize(16)
.margin({ top: 5 })
Button('修改@Prop数据(不会同步回父组件)')
.width('90%')
.margin({ top: 10 })
.onClick(() => {
this.propMessage = `子组件修改于 ${new Date().toLocaleTimeString()}`;
})
}
.width('100%')
.padding(10)
.backgroundColor(Color.White)
.borderRadius(10)
}
}
// 使用@Link的子组件
@Component
struct LinkChildComponent {
@Link linkCount: number;
build() {
Column() {
Text('@Link子组件')
.fontSize(18)
.fontColor(Color.Green)
Text(`计数: ${this.linkCount}`)
.fontSize(16)
.margin({ top: 5 })
Button('增加计数(会同步回父组件)')
.width('90%')
.margin({ top: 10 })
.onClick(() => {
this.linkCount++;
})
}
.width('100%')
.padding(10)
.backgroundColor(Color.White)
.borderRadius(10)
}
}
// 使用@ObjectLink的子组件
@Component
struct ObjectLinkChildComponent {
@ObjectLink objectLinkUser: User;
build() {
Column() {
Text('@ObjectLink子组件')
.fontSize(18)
.fontColor(Color.Orange)
Text(`用户: ${this.objectLinkUser.name}, 年龄: ${this.objectLinkUser.age}`)
.fontSize(16)
.margin({ top: 5 })
Button('增加年龄(会同步回父组件)')
.width('90%')
.margin({ top: 10 })
.onClick(() => {
this.objectLinkUser.age++;
})
}
.width('100%')
.padding(10)
.backgroundColor(Color.White)
.borderRadius(10)
}
}
// 使用@Consume的子组件
@Component
struct ConsumeChildComponent {
@Consume totalScore: number;
build() {
Column() {
Text('@Consume子组件')
.fontSize(18)
.fontColor(Color.Red)
Text(`总分: ${this.totalScore}`)
.fontSize(16)
.margin({ top: 5 })
Button('减少分数(会同步到所有@Provide)')
.width('90%')
.margin({ top: 10 })
.onClick(() => {
this.totalScore -= 5;
})
}
.width('100%')
.padding(10)
.backgroundColor(Color.White)
.borderRadius(10)
}
}
各装饰器详细说明
1. @Prop 装饰器
特点:
单向数据同步:从父组件到子组件
子组件内修改不会同步回父组件
适用于展示型组件
使用场景:
当父组件需要传递数据给子组件,但子组件不需要修改父组件数据时使用。
2. @Link 装饰器
特点:
双向数据同步:父子组件间双向同步
子组件修改会同步回父组件
需要使用$语法传递引用
使用场景:
当子组件需要修改父组件数据并同步回父组件时使用。
3. @Provide 和 @Consume 装饰器
特点:
跨层级数据同步:祖先组件和后代组件间直接同步
不需要逐层传递数据
任何一方修改都会同步到另一方
使用场景:
当需要跨越多层组件传递数据时使用,避免"属性 drilling"问题。
4. @Observed 和 @ObjectLink 装饰器
特点:
@Observed 装饰类,使其具备响应式能力
@ObjectLink 装饰对象属性,实现对象属性的双向同步
用于复杂对象的数据同步
使用场景:
当需要同步对象的属性而不是整个对象时使用。
使用建议
简单数据传递使用 @Prop 或 @Link
跨层级数据共享使用 @Provide 和 @Consume
对象属性同步使用 @Observed 和 @ObjectLink
根据数据流方向选择合适的装饰器
避免过度使用 @Provide 和 @Consume,以免造成数据流难以追踪
这个示例展示了各种装饰器的基本用法和区别,您可以通过运行代码并点击各个按钮来观察不同装饰器的行为差异。