HarmonyOS-Next-状态管理ObserverV2和Trace-装饰器实践
HarmonyOS Next 状态管理:ObserverV2和Trace 装饰器实践
目录
一、 @ObserverV2和@Trace 修饰器概述
在组件化开发中,我们常常需要对类对象的属性进行观测,以便在属性变化时自动更新 UI。
@ObservedV2
和
@Trace
正是为此设计的修饰器。
@ObservedV2
:用于装饰类,表明该类是可被观察的。单独使用@ObservedV2
无效,必须与@Trace
配合使用。@Trace
:用于装饰类的属性,表示该属性可以被精确跟踪和观察。@Trace
只能在被@ObservedV2
装饰的类中使用。
二、@ObserverV2和@Trace 修饰器的限制
使用范围 :
@ObservedV2
和@Trace
只能在ComponentV2
中使用。
搭配使用 :
@ObservedV2
必须与@Trace
搭配使用,单独使用任意一个修饰器都不会生效。
属性观测 :
- 只有被
@Trace
装饰的属性在变化时,才会通知关联的组件进行 UI 刷新。 - 未被
@Trace
装饰的属性无法触发 UI 刷新,即使其值发生变化。
嵌套类 :
- 在嵌套类中,只有嵌套类的属性被
@Trace
装饰,且嵌套类本身被@ObservedV2
装饰时,才能触发 UI 刷新。
继承类 :
- 在继承类中,父类或子类的属性被
@Trace
装饰,且该属性所在的类被@ObservedV2
装饰时,才能触发 UI 刷新。
三、实践探索
3.1 @ObserverV2和@Trace 的简单使用
@ObservedV2
class UserInfo {
@Trace name: string
age: number
constructor(name: string, age: number) {
this.name = name
this.age = age
}
}
@Entry
@ComponentV2
struct Index {
userInfo1: UserInfo = new UserInfo(“孙膑”, 29)
@Local userInfo2: UserInfo = new UserInfo(“张仪”, 26)
build() {
Column({space: 20}) {
Row({space: 8}) {
Text(
User-1,name:${this.userInfo1.name}
)
Text(
age:${this.userInfo1.age}
)
}
Row({space: 8}) {
Text(
User-2,name:${this.userInfo2.name}
)
Text(
age:${this.userInfo2.age}
)
}
Button(‘update name’)
.onClick(() => {
this.userInfo1.name += “-user1”
this.userInfo2.name += “-user2”
})
Button(‘update age’)
.onClick(() => {
this.userInfo1.age++
this.userInfo2.age++
})
}
.width(‘100%’)
}
}
关键点 :
@ObserverV2
和@Trace
装饰的类在组件中创建的时候,是否加其他装饰器修饰不影响属性的观测。- 只有
@Trace
装饰的属性在变化的时候才会刷新UI(例如:name),非@Trace
装饰的属性在变化时不会刷新UI(例如:age)
3.2 在类的嵌套中使用@ObserverV2和@Trace
@ObservedV2
class Address {
@Trace country: string
constructor(country: string) {
this.country = country
}
}
class Person {
name: string
address: Address
constructor(name: string, country: string) {
this.name = name
this.address = new Address(country)
}
}
@Entry
@ComponentV2
struct Index {
userInfo: UserInfo = new UserInfo(“孙膑”, “齐国”)
person: Person = new Person(“庞涓”, “魏国”)
build() {
Column({space: 20}) {
Row({space: 8}) {
Text(
name:${this.userInfo.name}
)
Text(
country:${this.userInfo.address.country}
)
}
Line().width(‘100%’).height(1).backgroundColor(Color.Gray)
Row({space: 8}) {
Text(
person_name:${this.person.name}
)
Text(
person_country:${this.person.address.country}
)
}
Button(‘update update’)
.onClick(() => {
this.userInfo.address.country = (this.userInfo.address.country == “齐国” ? “中国” : “齐国”)
this.person.address.country = (this.person.address.country == “魏国” ? “中国” : “魏国”)
})
}
.width(‘100%’)
}
}
关键点 :
- 嵌套类观测
:嵌套类中的属性必须被
@Trace
装饰,且嵌套类本身必须被@ObservedV2
装饰,才能触发 UI 刷新。 - 非观测属性
:未被
@Trace
装饰的属性(如Person
类中的name
)在变化时不会触发 UI 刷新
3.3 在继承类中使用@ObserverV2和@Trace
3.3.1 实践一, 父类不使用@ObserverV2和@Trace来装饰,子类使用@ObserverV2和@Trace来装饰
class Person {
name: string
constructor(name: string) {
this.name = name
}
}
@ObservedV2
class UserInfo extends Person {
@Trace age: number
constructor(name: string, age: number) {
super(name)
this.age = age
}
}
@Entry
@ComponentV2
struct Index {
userInfo: UserInfo = new UserInfo(“孙膑”, 29)
build() {
Column({space: 20}) {
Text(
name:${this.userInfo.name}
)
Text(
age:${this.userInfo.age}
)
Button(‘change value’)
.onClick(() => {
this.userInfo.name = (this.userInfo.name === “孙膑” ? “庞涓” : “孙膑”)
this.userInfo.age++
})
}
.width(‘100%’)
}
}
关键点 :
- 子类属性观测
:子类中被
@Trace
装饰的属性(如age
)在变化时会触发 UI 刷新。 - 父类属性
:父类中未被
@Trace
装饰的属性(如name
)在变化时不会触发 UI 刷新。
3.3.2 实践二, 父类使用@ObserverV2和@Trace来装饰,子类不使用@ObserverV2和@Trace来装饰
@ObservedV2
class Person {
@Trace name: string
constructor(name: string) {
this.name = name
}
}
class UserInfo extends Person {
age: number
constructor(name: string, age: number) {
super(name)
this.age = age
}
}
@Entry
@ComponentV2
struct Index {
userInfo: UserInfo = new UserInfo(“孙膑”, 29)
build() {
Column({space: 20}) {
Text(
name:${this.userInfo.name}
)
Text(
age:${this.userInfo.age}
)
Button(‘change value’)
.onClick(() => {
this.userInfo.name = (this.userInfo.name === “孙膑” ? “庞涓” : “孙膑”)
this.userInfo.age++
})
}
.width(‘100%’)
}
}
关键点 :
- 继承属性观测
:子类会继承父类中被
@Trace
装饰的属性的观测能力。 - 非观测属性
:子类中未被
@Trace
装饰的属性(如age
)在变化时不会触发 UI 刷新。
3.4 容器中的类使用@ObserverV2和@Trace
@ObservedV2
class UserInfo {
@Trace name: string
@Trace age: number
constructor(name: string, age: number) {
this.name = name
this.age = age
}
}
@Entry
@ComponentV2
struct Index {
@Local userInfos: UserInfo[] = [new UserInfo(“孙膑”, 29)]
build() {
Column({space: 20}) {
ForEach(this.userInfos, (userInfo: UserInfo) => {
Text(
name:${userInfo.name}
)
Text(
age:${userInfo.age}
)
Line().width(‘100%’).height(1).backgroundColor(Color.Gray)
})
Button(‘add item’)
.onClick(() => {
this.userInfos.push(new UserInfo(“庞涓”, 31))
})
Button(‘change property’)
.onClick(() => {
this.userInfos[0].name =
${Math.round(Math.random() * 100)}
this.userInfos[0].age++
})
}
.width(‘100%’)
}
}
关键点 :
- 容器中的对象观测
:容器中的对象如果被
@ObservedV2
和@Trace
装饰,其属性变化时会触发 UI 刷新。 - 动态更新 :通过操作容器(如添加或修改对象),可以动态更新 UI。
四、总结
通过
@ObservedV2
和
@Trace
修饰器,我们可以实现对类属性的精确观测,并在属性变化时自动更新 UI。关键点包括:
- 搭配使用
:
@ObservedV2
必须与@Trace
搭配使用。 - 属性观测
:只有被
@Trace
装饰的属性在变化时才会触发 UI 刷新。 - 嵌套与继承 :在嵌套类和继承类中,需要确保属性和类被正确装饰,才能实现属性观测。
- 容器中的对象 :容器中的对象如果被正确装饰,其属性变化也会触发 UI 刷新。
通过合理使用
@ObservedV2
和
@Trace
,可以显著提升组件化开发的效率和代码的可维护性。