# 14.9:@Monitor
ArkUI 开发框架提供了 @Monitor 装饰器来监听状态变量的修改,使得状态变量具有深度监听的能力,本节笔者简单介绍一下 @Monitor 的使用。
# 14.9.1:约束与限制
- @Monitor 只支持 @Local、@Param、@Provider 和 @Consumer 装饰的变量。
- @Monitor 允许在 @ObserverV2 的类内使用来监听 @Trace 装饰的变量。
- @Monitor 在继承类场景中,父子类同时监听同一个属性则会同时回调监听函数。
# 14.9.2:语法介绍
@Monitor 装饰器可以接收一个或多个装饰器参数,这些参数为状态属性名,中间用逗号隔开,然后装饰一个方法,并且要求该方法仅接收一个 IMonitor
类型的参数,格式为: @Monitor("attribute1", "attribute2", ..., "attributeN") function_name(monitor: IMonitor),样例如下所示:
@Entry @ComponentV2 struct Page_state {
@Local userName: string = "" // 定义状态变量userName
@Monitor("userName") // 使用@Monitor监听userName,如果userName变化了则执行notifyUserNameChanged()方法
notifyUserNameChanged(monitor: IMonitor) { // IMonitor包含了状态属性前后变化值和属性名
}
build() {
}
}
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
# 14.9.3:简单样例
@Monitor 的简单样例如下所示:
import { promptAction } from '@kit.ArkUI'
@Entry @ComponentV2 struct Page_state {
@Local userName: string = "张三" // 定义状态变量userName
@Monitor("userName") // 监听状态变量userName
notifyUserNameChanged(monitor: IMonitor) {
monitor.dirty.forEach((name) => {
let before = monitor.value(name)?.before as string
let now = monitor.value(name)?.now as string
promptAction.showToast({
message: "之前: " + before + ", 现在: " + now,
alignment: Alignment.Top
})
})
}
build() {
Column({space: 20}) {
Text(this.userName)
Button("更改用户名")
.onClick(() => {
this.userName = "李四:" + new Date().getMilliseconds();
})
}
.width("100%")
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
样例运行结果如下图所示:

# 14.9.4:使用场景
多属性监听
@Monitor 支持同时监听多个状态属性,简单样例如下所示:
import { promptAction } from '@kit.ArkUI' @Entry @ComponentV2 struct Page_state { @Local userName: string = "张三" @Local address: string = "北京" @Local birthday: string = "2020" @Monitor("userName", "address", "birthday") notifyUserNameChanged(monitor: IMonitor) { monitor.dirty.forEach((name) => { let before = monitor.value(name)?.before as string let now = monitor.value(name)?.now as string promptAction.showToast({ message: "之前: " + before + ", 现在: " + now, alignment: Alignment.Top }) }) } build() { Column({space: 20}) { Text(this.userName + ", " + this.address + ", " + this.birthday) Row({space: 10}) { Button("更改姓名") .onClick(() => { this.userName = "李四:" + new Date().getMilliseconds(); }) Button("更改住址") .onClick(() => { this.address = "北京:" + new Date().getMilliseconds(); }) Button("更改生日") .onClick(() => { this.birthday = "2020:" + new Date().getMilliseconds(); }) } } .width("100%") } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43样例运行结果如下图所示:
类对象监听
@Monitor支持监听状态对象,也就是说只支持对状态对象本身赋值操作做监听,简单样例如下所示:
import { promptAction } from '@kit.ArkUI' class User { userName: string; address: string; constructor(userName: string, address: string) { this.userName = userName; this.address = address; } } @Entry @ComponentV2 struct Page_state { @Local user: User = new User("张三", "北京") @Monitor("user") notifyUserNameChanged(monitor: IMonitor) { monitor.dirty.forEach((name) => { let before = JSON.stringify(monitor.value(name)?.before) let now = JSON.stringify(monitor.value(name)?.now) promptAction.showToast({ message: "之前: " + before + ", 现在: " + now, alignment: Alignment.Top }) }) } build() { Column({space: 20}) { Text("用户:" + this.user.userName + ", " + this.user.address) Row({space: 10}) { Button("更改用户") .onClick(() => { this.user = new User("李四", "上海"); // Text刷新 }) Button("更改姓名") .onClick(() => { this.user.userName = "王五" // Text不变 }) } } .width("100%") } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47样例运行结果如下图所示:
多层次监听
@Monitor支持监听状态对象内被@Trace修饰的属性,简单样例如下所示:
import { promptAction } from '@kit.ArkUI' @ObservedV2 class User { @Trace userName: string; @Trace address: string; constructor(userName: string, address: string) { this.userName = userName; this.address = address; } } @Entry @ComponentV2 struct Page_state { @Local user: User = new User("张三", "北京") // 定义状态属性 @Monitor("user", "user.userName") // 监听状态,注意监听状态对象的状态属性的写法 notifyUserNameChanged(monitor: IMonitor) { // 监听回调 monitor.dirty.forEach((name) => { let before = JSON.stringify(monitor.value(name)?.before) let now = JSON.stringify(monitor.value(name)?.now) promptAction.showToast({ message: "之前: " + before + ", 现在: " + now, alignment: Alignment.Top }) }) } build() { Column({space: 20}) { Text("用户:" + this.user.userName + ", " + this.user.address) Row({space: 10}) { Button("更改用户") .onClick(() => { this.user = new User("李四", "上海"); // 可以监听 }) Button("更改姓名") .onClick(() => { this.user.userName = "王五" // 可以监听 }) } } .width("100%") } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51简单样例如下图所示:
📢:监听状态类对象的属性时,注意属性名的写法。
多继承监听
@Monitor在继承类场景下,可以在继承链中对同一个属性进行多次监听,简单样例如下所示:
@ObservedV2 class Base { @Trace userName: string; constructor(userName: string) { this.userName = userName; } @Monitor("userName") notifyUserNameChangedInBase(monitor: IMonitor) { console.log("notifyUserNameChangedInBase: " + JSON.stringify(monitor)) } } @ObservedV2 class Parent extends Base { constructor(userName: string) { super(userName); } @Monitor("userName") notifyUserNameChangedInParent(monitor: IMonitor) { console.log("notifyUserNameChangedInParent: " + JSON.stringify(monitor)) } } @ObservedV2 class User extends Parent { @Trace address: string; constructor(userName: string, address: string) { super(userName); this.address = address; } @Monitor("userName") notifyUserNameChangedInUser(monitor: IMonitor) { console.log("notifyUserNameChangedInUser: " + JSON.stringify(monitor)) } } @Entry @ComponentV2 struct Page_state { @Local user: User = new User("张三", "北京") // 定义状态属性 build() { Column({space: 20}) { Text("用户:" + this.user.userName + ", " + this.user.address) Row({space: 10}) { Button("更改用户") .onClick(() => { this.user = new User("李四", "上海"); }) Button("更改姓名") .onClick(() => { this.user.userName = "王五" // 可以监听 }) } } .width("100%") } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63样例运行结果如下图所示:
点击
更改姓名
按钮,控制台日志打印如下:

请作者喝杯咖啡
©arkui.club版权所有,禁止私自转发、克隆网站。