1# 自定义组件成员属性访问限定符使用限制 2<!--Kit: ArkUI--> 3<!--Subsystem: ArkUI--> 4<!--Owner: @BlYynNe--> 5<!--Designer: @lixingchi1--> 6<!--Tester: @TerryTsao--> 7<!--Adviser: @zhang_yixin13--> 8 9在状态管理V1版本中,完成自定义组件封装后,调用方难以明确知晓应传入哪些变量作为组件的输入参数。当组件开发者不希望状态变量被外部初始化时,可以使用private限定符来限制当前变量不允许被进行外部初始化。外部初始化也需要遵循装饰器自身的规则,具体规则见[使用限制](#使用限制)。 10 11ArkTS会对自定义组件的成员变量使用的访问限定符private/public/protected进行校验,当不按规范使用访问限定符private/public/protected时,会产生对应的日志信息。 12 13在阅读本文档前,建议提前阅读:[状态管理概述](./arkts-state-management-overview.md)。 14 15> **说明:** 16> 17> 从API version 12开始,支持自定义组件成员属性访问限定符使用限制的规则。 18 19## 使用限制 20 21- [\@State](./arkts-state.md)/[\@Prop](./arkts-prop.md)/[\@Provide](./arkts-provide-and-consume.md)/[\@BuilderParam](./arkts-builderparam.md)/常规成员变量(不涉及更新的普通变量)的初始化规则为可以被外部初始化,也可以使用本地值进行初始化。当组件开发者不希望当前变量被外部初始化时,可以使用private进行修饰,在这种情况下,错误进行外部初始化会有编译告警日志提示。 22 23- [\@StorageLink](./arkts-appstorage.md#storagelink)/[\@StorageProp](./arkts-appstorage.md#storageprop)/[\@LocalStorageLink](./arkts-localstorage.md#localstoragelink)/[\@LocalStorageProp](./arkts-localstorage.md#localstorageprop)/[\@Consume](./arkts-provide-and-consume.md)变量的初始化规则为不可以被外部初始化,当组件开发者希望当前变量被外部初始化而使用public修饰时,与装饰器本身的初始化规则不符,会有编译告警日志提示。 24 25- [\@Link](./arkts-link.md)/[\@ObjectLink](./arkts-observed-and-objectlink.md)变量的初始化规则为必须被外部初始化,禁止本地初始化。当组件开发者使用private对变量进行修饰时,与装饰器本身的初始化规则不符,会有编译告警日志提示。 26 27- 由于struct没有继承能力,上述所有的这些变量使用protected修饰时,会有编译告警日志提示。 28 29- [\@Require](./arkts-require.md)含义是当前被\@Require装饰的变量必须被外部初始化,当\@Require和private同时装饰[\@State](./arkts-state.md)/[\@Prop](./arkts-prop.md)/[\@Provide](./arkts-provide-and-consume.md)/[\@BuilderParam](./arkts-builderparam.md)/常规成员变量(不涉及更新的普通变量)时,他们的含义是自相矛盾的,会有编译告警日志提示。 30 31## 使用场景 32 331. 当成员变量被private访问限定符和\@State/\@Prop/\@Provide/\@BuilderParam装饰器同时修饰,并且通过父组件进行初始化赋值,ArkTS会进行校验并产生告警日志。 34 35 【反例】 36 ```ts 37 @Entry 38 @Component 39 struct AccessRestrictions { 40 @Builder 41 buildTest() { 42 Text('Parent builder') 43 } 44 45 build() { 46 Column() { 47 ComponentsChild({ 48 state_value: 'Hello', 49 prop_value: 'Hello', 50 provide_value: 'Hello', 51 builder_value: this.buildTest, 52 regular_value: 'Hello' 53 }) 54 } 55 .width('100%') 56 } 57 } 58 59 @Component 60 struct ComponentsChild { 61 // 此处使用private修饰符时会出现告警日志 62 @State private state_value: string = 'Hello'; 63 // 此处使用private修饰符时会出现告警日志 64 @Prop private prop_value: string = 'Hello'; 65 // 此处使用private修饰符时会出现告警日志 66 @Provide private provide_value: string = 'Hello'; 67 // 此处使用private修饰符时会出现告警日志 68 @BuilderParam private builder_value: () => void = this.buildTest; 69 // 此处使用private修饰符时会出现告警日志 70 private regular_value: string = 'Hello'; 71 72 @Builder 73 buildTest() { 74 Text('Child builder') 75 } 76 77 build() { 78 Column() { 79 Text('Hello') 80 .fontSize(50) 81 .fontWeight(FontWeight.Bold) 82 } 83 } 84 } 85 ``` 86 87 编译告警日志如下: 88 89 ```ts 90 Property 'state_value' is private and can not be initialized through the component constructor. 91 Property 'prop_value' is private and can not be initialized through the component constructor. 92 Property 'provide_value' is private and can not be initialized through the component constructor. 93 Property 'builder_value' is private and can not be initialized through the component constructor. 94 Property 'regular_value' is private and can not be initialized through the component constructor. 95 ``` 96 97 【正例】 98 ```ts 99 @Entry 100 @Component 101 struct AccessRestrictions { 102 @Builder 103 buildTest() { 104 Text('Parent builder') 105 } 106 107 build() { 108 Column() { 109 ComponentsChild({ 110 state_value: 'Hello', 111 prop_value: 'Hello', 112 provide_value: 'Hello', 113 builder_value: this.buildTest, 114 regular_value: 'Hello' 115 }) 116 } 117 .width('100%') 118 } 119 } 120 121 @Component 122 struct ComponentsChild { 123 @State state_value: string = 'Hello'; 124 @Prop prop_value: string = 'Hello'; 125 @Provide provide_value: string = 'Hello'; 126 @BuilderParam builder_value: () => void = this.buildTest; 127 regular_value: string = 'Hello'; 128 129 @Builder 130 buildTest() { 131 Text('Child builder') 132 } 133 134 build() { 135 Column() { 136 Text('Hello') 137 .fontSize(50) 138 .fontWeight(FontWeight.Bold) 139 } 140 } 141 } 142 ``` 143 1442. 当成员变量被public访问限定符和\@StorageLink/\@StorageProp/\@LocalStorageLink/\@LocalStorageProp/\@Consume装饰器同时修饰,并且通过父组件进行初始化赋值,ArkTS会进行校验并产生告警日志。 145 146 【反例】 147 ```ts 148 @Entry 149 @Component 150 struct AccessRestrictions { 151 @Provide consume_value: string = 'Hello'; 152 build() { 153 Column() { 154 ComponentChild() 155 } 156 .width('100%') 157 } 158 } 159 160 @Component 161 struct ComponentChild { 162 // 此处使用public修饰符时会出现告警日志 163 @LocalStorageProp('sessionLocalProp') public local_prop_value: string = 'Hello'; 164 // 此处使用public修饰符时会出现告警日志 165 @LocalStorageLink('sessionLocalLink') public local_link_value: string = 'Hello'; 166 // 此处使用public修饰符时会出现告警日志 167 @StorageProp('sessionProp') public storage_prop_value: string = 'Hello'; 168 // 此处使用public修饰符时会出现告警日志 169 @StorageLink('sessionLink') public storage_link_value: string = 'Hello'; 170 // 此处使用public修饰符时会出现告警日志 171 @Consume public consume_value: string; 172 173 build() { 174 Column() { 175 Text('Hello') 176 .fontSize(50) 177 .fontWeight(FontWeight.Bold) 178 } 179 } 180 } 181 ``` 182 183 编译告警日志如下: 184 185 ```ts 186 Property 'local_prop_value' can not be decorated with both '@LocalStorageProp' and public. 187 Property 'local_link_value' can not be decorated with both '@LocalStorageLink' and public. 188 Property 'storage_prop_value' can not be decorated with both '@StorageProp' and public. 189 Property 'storage_link_value' can not be decorated with both '@StorageLink' and public. 190 Property 'consume_value' can not be decorated with both '@Consume' and public. 191 ``` 192 193 【正例】 194 ```ts 195 @Entry 196 @Component 197 struct AccessRestrictions { 198 @Provide consume_value: string = 'Hello'; 199 build() { 200 Column() { 201 ComponentChild() 202 } 203 .width('100%') 204 } 205 } 206 207 @Component 208 struct ComponentChild { 209 @LocalStorageProp('sessionLocalProp') local_prop_value: string = 'Hello'; 210 @LocalStorageLink('sessionLocalLink') local_link_value: string = 'Hello'; 211 @StorageProp('sessionProp') storage_prop_value: string = 'Hello'; 212 @StorageLink('sessionLink') storage_link_value: string = 'Hello'; 213 @Consume consume_value: string; 214 build() { 215 Column() { 216 Text('Hello') 217 .fontSize(50) 218 .fontWeight(FontWeight.Bold) 219 } 220 } 221 } 222 ``` 223 2243. 当成员变量被private访问限定符和\@Link/\@ObjectLink装饰器同时修饰,并且通过父组件进行初始化赋值,ArkTS会进行校验并产生告警日志。 225 226 【反例】 227 ```ts 228 @Entry 229 @Component 230 struct AccessRestrictions { 231 @State link_value: string = 'Hello'; 232 @State objectLink_value: ComponentObj = new ComponentObj(); 233 build() { 234 Column() { 235 ComponentChild({link_value: this.link_value, objectLink_value: this.objectLink_value}) 236 } 237 .width('100%') 238 } 239 } 240 241 @Observed 242 class ComponentObj { 243 count: number = 0; 244 } 245 @Component 246 struct ComponentChild { 247 // 此处使用private修饰符时会出现告警日志 248 @Link private link_value: string; 249 // 此处使用private修饰符时会出现告警日志 250 @ObjectLink private objectLink_value: ComponentObj; 251 build() { 252 Column() { 253 Text('Hello') 254 .fontSize(50) 255 .fontWeight(FontWeight.Bold) 256 } 257 } 258 } 259 ``` 260 261 编译告警日志如下: 262 263 ```ts 264 Property 'link_value' can not be decorated with both '@Link' and private. 265 Property 'objectLink_value' can not be decorated with both '@ObjectLink' and private. 266 ``` 267 268 【正例】 269 ```ts 270 @Entry 271 @Component 272 struct AccessRestrictions { 273 @State link_value: string = 'Hello'; 274 @State objectLink_value: ComponentObj = new ComponentObj(); 275 build() { 276 Column() { 277 ComponentChild({link_value: this.link_value, objectLink_value: this.objectLink_value}) 278 } 279 .width('100%') 280 } 281 } 282 283 @Observed 284 class ComponentObj { 285 count: number = 0; 286 } 287 @Component 288 struct ComponentChild { 289 @Link link_value: string; 290 @ObjectLink objectLink_value: ComponentObj; 291 build() { 292 Column() { 293 Text('Hello') 294 .fontSize(50) 295 .fontWeight(FontWeight.Bold) 296 } 297 } 298 } 299 ``` 300 3014. 当成员变量被protected访问限定符修饰,并且通过父组件进行初始化赋值,ArkTS会进行校验并产生告警日志。 302 303 【反例】 304 ```ts 305 @Entry 306 @Component 307 struct AccessRestrictions { 308 build() { 309 Column() { 310 ComponentChild({regular_value: 'Hello'}) 311 } 312 .width('100%') 313 } 314 } 315 316 @Component 317 struct ComponentChild { 318 // 此处使用protected修饰符时会出现告警日志 319 protected regular_value: string = 'Hello'; 320 build() { 321 Column() { 322 Text('Hello') 323 .fontSize(50) 324 .fontWeight(FontWeight.Bold) 325 } 326 } 327 } 328 ``` 329 330 编译告警日志如下: 331 332 ```ts 333 The member attributes of a struct can not be protected. 334 ``` 335 336 【正例】 337 ```ts 338 @Entry 339 @Component 340 struct AccessRestrictions { 341 build() { 342 Column() { 343 ComponentChild({regular_value: 'Hello'}) 344 } 345 .width('100%') 346 } 347 } 348 349 @Component 350 struct ComponentChild { 351 regular_value: string = 'Hello'; 352 build() { 353 Column() { 354 Text('Hello') 355 .fontSize(50) 356 .fontWeight(FontWeight.Bold) 357 } 358 } 359 } 360 ``` 361 3625. 当成员变量被private访问限定符、\@Require和@State/@Prop/@Provide/@BuilderParam装饰器同时修饰,并且通过父组件初始化赋值时,ArkTS会进行校验并产生告警日志。 363 364 【反例】 365 ```ts 366 @Entry 367 @Component 368 struct AccessRestrictions { 369 build() { 370 Column() { 371 ComponentChild({prop_value: 'Hello'}) 372 } 373 .width('100%') 374 } 375 } 376 @Component 377 struct ComponentChild { 378 // 此处使用private修饰符时会出现告警日志 379 @Require @Prop private prop_value: string = 'Hello'; 380 build() { 381 Column() { 382 Text('Hello') 383 .fontSize(50) 384 .fontWeight(FontWeight.Bold) 385 } 386 } 387 } 388 ``` 389 390 编译告警日志如下: 391 392 ```ts 393 Property 'prop_value' can not be decorated with both '@Require' and private. 394 Property 'prop_value' is private and can not be initialized through the component constructor. 395 ``` 396 397 【正例】 398 ```ts 399 @Entry 400 @Component 401 struct AccessRestrictions { 402 build() { 403 Column() { 404 ComponentChild({prop_value: 'Hello'}) 405 } 406 .width('100%') 407 } 408 } 409 @Component 410 struct ComponentChild { 411 @Require @Prop prop_value: string = 'Hello'; 412 build() { 413 Column() { 414 Text('Hello') 415 .fontSize(50) 416 .fontWeight(FontWeight.Bold) 417 } 418 } 419 } 420 ```