• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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    ```