@ObservedV2装饰器和@Trace装饰器:类属性变化观测
ObservedV2和Trace需要一起使用,作用是监听类属性的变化
在下面的例子中如果没有加入上述两个装饰器,则不会监听属性的变化
ts
@ObservedV2
class UserInfo {
@Trace name: string = ""
}
@Entry
@ComponentV2
struct Index {
userinfo: UserInfo = new UserInfo()
build() {
Column() {
Text(this.userinfo.name)
Button("click")
.onClick(()=>{
this.userinfo.name = 'lele'
})
}
.height('100%')
.width('100%')
}
}
上述装饰器的强大不止于此,在嵌套类中一样可以检测
ts
@ObservedV2
class UserInfo {
@Trace name: string = ""
}
class User extends UserInfo{}
@Entry
@ComponentV2
struct Index {
user: User = new User()
build() {
Column() {
Text(this.user.name)
Button("click")
.onClick(()=>{
this.user.name = 'lele'
})
}
.height('100%')
.width('100%')
}
}
@Monitor装饰器:状态变量修改异步监听
@Monitor监听的变量需要被@Local、@Param、@Provider、@Consumer、@Computed装饰,未被状态变量装饰器装饰的变量在变化时无法被监听。@Monitor可以同时监听多个状态变量,这些变量名之间用","隔开。
ts
@Entry
@ComponentV2
struct Index {
@Local name:string = ''
@Monitor('name')
nameChange(monitor:IMonitor){
// 获取值
this.getUIContext().getPromptAction().showToast({
message:`path: ${monitor.value()?.path} change from ${monitor.value()?.before} to ${monitor.value()?.now}`
})
// output: path: name change from to lele`
// monitor.dirty 变化路径的数组。
this.getUIContext().getPromptAction().showToast({
message:`dirty: ${monitor.dirty}`
})
// output:dirty:name
}
build() {
Column() {
Text(this.name)
Button("click")
.onClick(()=>{
this.name = 'lele'
})
}
.height('100%')
.width('100%')
}
}
当name改变时,会触发nameChange方法
@SyncMonitor装饰器:状态变量修改同步监听
api23才有
@SyncMonitor装饰器用于同步监听状态变量修改,使得状态变量具有深度监听的能力:
SyncMonitor可以监听深层属性的变化,并能够根据更改前后的值做分类处理。
ts
@ObservedV2
class Info {
@Trace public value: number = 50;
}
@ObservedV2
class UIStyle {
public info: Info = new Info();
@Trace public color: Color = Color.Black;
@Trace public fontSize: number = 45;
@SyncMonitor('info.value')
onValueChange(monitor: IMonitor) {
let lastValue: number = monitor.value()?.before as number;
let curValue: number = monitor.value()?.now as number;
if (lastValue != 0) {
let diffPercent: number = (curValue - lastValue) / lastValue;
if (diffPercent > 0.1) {
this.color = Color.Red;
this.fontSize = 50;
} else if (diffPercent < -0.1) {
this.color = Color.Green;
this.fontSize = 40;
} else {
this.color = Color.Black;
this.fontSize = 45;
}
}
}
}
@Entry
@ComponentV2
struct Index {
textStyle: UIStyle = new UIStyle();
build() {
Column() {
Text(`Important Value: ${this.textStyle.info.value}`)
.fontColor(this.textStyle.color)
.fontSize(this.textStyle.fontSize)
Button('change!')
.onClick(() => {
this.textStyle.info.value = Math.floor(Math.random() * 100) + 1;
})
}
}
}
@Computed装饰器:计算属性
当开发者使用相同的计算逻辑重复绑定在UI上时,为了防止重复计算,可以使用@Computed计算属性。计算属性中依赖的状态变量变化时,只会计算一次。这解决了UI多次重用该属性导致的重复计算和性能问题。
ts
@Entry
@ComponentV2
struct Index {
@Local firstname:string = 'shui'
@Local lastname:string = 'shenhuole'
fullNameFunc():string{
console.log('fullNameFun');
return this.firstname + this.lastname
}
@Computed
get fullName(){
console.log('fullName');
return this.fullNameFunc()
}
build() {
Column(){
Text(`${this.fullNameFunc()}`)
Text(`${this.fullNameFunc()}`)
Text(`${this.fullNameFunc()}`)
Text(`${this.fullNameFunc()}`)
Text(`${this.fullName}`)
Text(`${this.fullName}`)
Text(`${this.fullName}`)
Text(`${this.fullName}`)
}
}
}
输出结果 在使用@computed装饰器的属性时,会自动缓存计算结果,下次使用时,会直接返回缓存结果,而不会重复计算。
bash
03-23 23:18:38.016 7683-7683 A03d00/JSAPP com.examp...lication I fullName
03-23 23:18:38.016 7683-7683 A03d00/JSAPP com.examp...lication I fullNameFun
03-23 23:18:38.021 7683-7683 A03d00/JSAPP com.examp...lication I fullNameFun
03-23 23:18:38.022 7683-7683 A03d00/JSAPP com.examp...lication I fullNameFun
03-23 23:18:38.023 7683-7683 A03d00/JSAPP com.examp...lication I fullNameFun
03-23 23:18:38.023 7683-7683 A03d00/JSAPP com.examp...lication I fullNameFun