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