1# \@Track装饰器:class对象属性级更新
2
3
4\@Track应用于class对象的属性级更新。\@Track装饰的属性变化时,只会触发该属性关联的UI更新。
5
6
7在阅读本文档之前,建议开发者对状态管理基本观察能力有基本的了解。建议提前阅读:[\@State](./arkts-state.md)。
8
9> **说明:**
10>
11> 从API version 11开始,该装饰器支持在ArkTS卡片中使用。
12
13
14## 概述
15
16\@Track是class对象的属性装饰器。当一个class对象是状态变量时,\@Track装饰的属性发生变化,只会触发该属性关联的UI更新;如果class类中使用了\@Track装饰器,则未被\@Track装饰器装饰的属性不能在UI中使用,如果使用,会发生运行时报错。
17
18
19## 装饰器说明
20
21| \@Track变量装饰器  | 说明                  |
22| ------------------ | -------------------- |
23| 装饰器参数   | 无 |
24| 可装饰的变量 | class对象的非静态成员属性。 |
25
26
27
28## 观察变化和行为表现
29
30当一个class对象是状态变量时,\@Track装饰的属性发生变化,该属性关联的UI触发更新。
31
32> **说明:**
33>
34> 当class对象中没有一个属性被标记\@Track,行为与原先保持不变。\@Track没有深度观测的功能。
35
36使用\@Track装饰器可以避免冗余刷新。
37
38```ts
39class LogTrack {
40  @Track str1: string;
41  @Track str2: string;
42
43  constructor(str1: string) {
44    this.str1 = str1;
45    this.str2 = 'World';
46  }
47}
48
49class LogNotTrack {
50  str1: string;
51  str2: string;
52
53  constructor(str1: string) {
54    this.str1 = str1;
55    this.str2 = '世界';
56  }
57}
58
59@Entry
60@Component
61struct AddLog {
62  @State logTrack: LogTrack = new LogTrack('Hello');
63  @State logNotTrack: LogNotTrack = new LogNotTrack('你好');
64
65  isRender(index: number) {
66    console.log(`Text ${index} is rendered`);
67    return 50;
68  }
69
70  build() {
71    Row() {
72      Column() {
73        Text(this.logTrack.str1) // Text1
74          .fontSize(this.isRender(1))
75          .fontWeight(FontWeight.Bold)
76        Text(this.logTrack.str2) // Text2
77          .fontSize(this.isRender(2))
78          .fontWeight(FontWeight.Bold)
79        Button('change logTrack.str1')
80          .onClick(() => {
81            this.logTrack.str1 = 'Bye';
82          })
83        Text(this.logNotTrack.str1) // Text3
84          .fontSize(this.isRender(3))
85          .fontWeight(FontWeight.Bold)
86        Text(this.logNotTrack.str2) // Text4
87          .fontSize(this.isRender(4))
88          .fontWeight(FontWeight.Bold)
89        Button('change logNotTrack.str1')
90          .onClick(() => {
91            this.logNotTrack.str1 = '再见';
92          })
93      }
94      .width('100%')
95    }
96    .height('100%')
97  }
98}
99```
100
101在上面的示例中:
102
1031. 类LogTrack中的属性均被\@Track装饰器装饰,点击按钮"change logTrack.str1",此时Text1刷新,Text2不刷新,只有一条日志输出,避免了冗余刷新。
104    ```ts
105    Text 1 is rendered
106    ```
107
1082. 类logNotTrack中的属性均未被\@Track装饰器装饰,点击按钮"change logNotTrack.str1",此时Text3、Text4均会刷新,有两条日志输出,存在冗余刷新。
109    ```ts
110    Text 3 is rendered
111    Text 4 is rendered
112    ```
113
114## 限制条件
115
116- 如果class类中使用了\@Track装饰器,那么该class类中非\@Track装饰的属性不能在UI中使用,包括不能绑定在组件上、不能用于初始化子组件,错误的使用将导致运行时报错,详见[在UI中使用非\@Track装饰的属性发生运行时报错](#在ui中使用非track装饰的属性发生运行时报错);可以在非UI中使用非\@Track装饰的属性,如事件回调函数中、生命周期函数中等。
117
118- 建议开发者不要混用包含\@Track的class对象和不包含\@Track的class对象,如联合类型中、类继承中等。
119
120
121## 使用场景
122
123### \@Track和自定义组件更新
124
125以下示例展示组件更新和\@Track的处理步骤。对象log是\@State装饰的状态变量,logInfo是\@Track的成员属性,其余成员属性都是非\@Track装饰的,而且也不准备在UI中更新它们的值。
126
127
128```ts
129class Log {
130  @Track logInfo: string;
131  owner: string;
132  id: number;
133  time: Date;
134  location: string;
135  reason: string;
136
137  constructor(logInfo: string) {
138    this.logInfo = logInfo;
139    this.owner = 'OH';
140    this.id = 0;
141    this.time = new Date();
142    this.location = 'CN';
143    this.reason = 'NULL';
144  }
145}
146
147@Entry
148@Component
149struct AddLog {
150  @State log: Log = new Log('origin info.');
151
152  build() {
153    Row() {
154      Column() {
155        Text(this.log.logInfo)
156          .fontSize(50)
157          .fontWeight(FontWeight.Bold)
158          .onClick(() => {
159            // 没有被@Track装饰的属性可以在点击事件中使用。
160            console.log('owner: ' + this.log.owner +
161              ' id: ' + this.log.id +
162              ' time: ' + this.log.time +
163              ' location: ' + this.log.location +
164              ' reason: ' + this.log.reason);
165            this.log.time = new Date();
166            this.log.id++;
167
168            this.log.logInfo += ' info.';
169          })
170      }
171      .width('100%')
172    }
173    .height('100%')
174  }
175}
176```
177
178处理步骤:
179
1801. AddLog自定义组件的Text.onClick点击事件自增字符串' info.'。
181
1822. 由于\@State log变量的\@Track属性logInfo更改,Text重新渲染。
183
184## 常见问题
185
186### 在UI中使用非\@Track装饰的属性发生运行时报错
187
188在UI中使用非\@Track装饰的属性,运行时会报错。
189
190```ts
191class Person {
192  // id被@Track装饰
193  @Track id: number;
194  // age未被@Track装饰
195  age: number;
196
197  constructor(id: number, age: number) {
198    this.id = id;
199    this.age = age;
200  }
201}
202
203@Entry
204@Component
205struct Parent {
206  @State parent: Person = new Person(2, 30);
207
208  build() {
209    // 没有被@Track装饰的属性不可以在UI中使用,运行时会报错
210    Text(`Parent id is: ${this.parent.id} and Parent age is: ${this.parent.age}`)
211  }
212}
213```
214