鸿蒙HarmonyOS状态管理装饰器详解
装饰器概述
装饰器 | 说明 | 使用场景 |
---|---|---|
@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,以免造成数据流难以追踪
这个示例展示了各种装饰器的基本用法和区别,您可以通过运行代码并点击各个按钮来观察不同装饰器的行为差异。