鸿蒙开发中V2状态管理的使用(下)
继上篇文章之后,本篇说一下其他几个V2版本装饰器。本文最后将附上示例代码。
继上篇文章鸿蒙开发中V2状态管理的使用(上)之后,本篇说一下其他几个V2版本装饰器。
完整使用方法请参考官方文档:状态管理(V2)
本文最后将附上示例代码
1、@Event:规范组件输出
由于 @Param 装饰的变量在本地无法更改,使用 @Event 装饰器装饰回调方法并调用,可以实现更新数据源的变量,再通过 @Local 的同步机制,将修改同步回 @Param 装饰的变量,以此达到主动更新 @Param 装饰变量的效果。
@Event 主要配合 @Param 实现数据的双向同步
示例代码如下:
@Entry
@ComponentV2
struct Event_Case {
@Local num: number = 1
build() {
Column({ space: 20}){
Column({ space: 15}){
Text('父组件').fontSize(20)
Text(`${this.num}`).fontSize(18)
}
.width('90%')
.padding(20)
.border({width: 2, color: "#000", radius: 15})
Child({
num: this.num,
changeNum: () => this.num += 1
})
}
.padding({ top: 40})
.height('100%')
.width('100%')
}
}
@ComponentV2
struct Child {
@Param num: number = 1
@Event changeNum: (val: number) => void
build() {
Column({ space: 10}){
Text('子组件').fontSize(20)
Text(`${this.num}`).fontSize(18)
Button('修改 num')
.onClick(() => this.changeNum(this.num))
}
.width('90%')
.padding(10)
.border({width: 2, color: "#000", radius: 15})
}
}
效果如下:

2、@Monitor:状态变量修改异步监听
该装饰器类似 V1 中的 @Watch,但是 @Watch 只能监听单个状态变量,而且观察能力为一层;而 @Monitor 可以同时监听多个状态变量,而且具有深度监听的能力,具体对比如下:
| 用法 | @Watch | @Monitor |
|---|---|---|
| 参数 | 回调方法名。 | 监听状态变量名、属性名。 |
| 监听目标数 | 只能监听单个状态变量。 | 能同时监听多个状态变量。 |
| 监听能力 | 跟随状态变量观察能力(一层)。 | 跟随状态变量观察能力(深层)。 |
| 能否获取变化前的值 | 不能获取变化前的值。 | 能获取变化前的值。 |
| 监听条件 | 监听对象为状态变量。 | 监听对象为状态变量或为@Trace装饰的类成员属性。 |
| 使用限制 | 仅能在@Component装饰的自定义组件中使用。 | 能在@ComponentV2装饰的自定义组件中使用,也能在@ObservedV2装饰的类中使用。 |
使用方法如下:
(1)监听多个变量,并获取变化前后的值
@Monitor监听的变量需要被@Local、@Param、@Provider、@Consumer、@Computed装饰,未被状态变量装饰器装饰的变量在变化时无法被监听。如果同时监听多个状态变量,这些变量名之间用","隔开。
@Entry
@ComponentV2
struct Monitor_Case {
@Local message: string = 'Hello World';
@Local num: number = 0
@Monitor('message', 'num')
dataChange(monitor: IMonitor) {
monitor.dirty.forEach((path: string) => {
console.warn(`${path} changed from ${monitor.value(path)?.before} to ${monitor.value(path)?.now}`);
});
}
build() {
Column() {
Text(this.message).fontSize(20)
Text(`${this.num}`).fontSize(20)
Button('修改变量')
.onClick(() => {
this.message += '#'
this.num += 1
})
}
.height('100%')
.width('100%')
.padding({ top: 50 })
}
}
效果如下:

(2)@Monitor监听的状态变量为类对象时,仅能监听对象整体的变化。监听类属性的变化需要类属性被@Trace装饰。
class Person {
public name: string;
public age: number;
constructor(name: string, age: number) {
this.name = name;
this.age = age;
}
}
@Entry
@ComponentV2
struct Monitor_Case {
@Local message: string = 'Hello World';
@Local num: number = 0
@Local person: Person = new Person('张三', 18);
@Monitor('message', 'num', 'person')
dataChange(monitor: IMonitor) {
monitor.dirty.forEach((path: string) => {
console.warn(`${path} changed from ${JSON.stringify(monitor.value(path)?.before)} to ${JSON.stringify(monitor.value(path)?.now)}`);
});
}
build() {
Column() {
Text(this.message).fontSize(20)
Text(`${this.num}`).fontSize(20)
Text(this.person.name).fontSize(20)
Button('修改变量')
.onClick(() => {
this.message += '#'
this.num += 1
// this.person.name += "*" // 无法监听到变化
this.person = new Person('李四', 20) // 可以监听到变化
})
}
.height('100%')
.width('100%')
.padding({ top: 50 })
}
}

上面这种方式只能通过修改对象整体才能被监听到变化。
如果想通过 this.person.name += '*' 的方式来监听对象中某一个属性的变化,则需要在类上增加 @ObservedV2 装饰器,而且被监听的变量需要添加 @Trace 装饰器:
@ObservedV2
class Person {
@Trace public name: string;
public age: number;
constructor(name: string, age: number) {
this.name = name;
this.age = age;
}
}
@Monitor('person.name')
dataChange(monitor: IMonitor) {
monitor.dirty.forEach((path: string) => {
console.warn(`${path} changed from ${JSON.stringify(monitor.value(path)?.before)} to ${JSON.stringify(monitor.value(path)?.now)}`);
});
}
此时,就可以监听对象中某一个属性了,效果如下:

【限制条件】不建议在一个类中对同一个属性进行多次@Monitor的监听。当一个类中存在对一个属性的多次监听时,只有最后一个定义的监听方法会生效。具体可参考官方案例:限制条件
示例代码见gitee仓库:V2状态管理
更多推荐



所有评论(0)