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