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