1# Mixing Use of Custom Components
2
3For the \@Component decorated custom components (referred to as the custom components of V1), corresponding state variable decorators (referred to as the decorators of V1), such as \@State, \@Prop, and \@Link, are provided. However, state management V1 (V1 for short) has many restrictions on the observation of nested classes. For example, you need to use \@ObjectLink to continuously disassemble nested classes so that in-depth data can be observed. Therefore, a new set of state management V2 (V2 for short) is developed in API version 12. You can declare \@ComponentV2 decorated custom components (referred to as custom components of V2) and use them with new decorators (referred to as the decorators of V2), such as \@Local and \@Param. The proposal of V2 not only compensates the deficiency of V1 in nested class observation, but also enhances some decorator functions. For example, compared with \@Watch of V1, \@Monitor of V2 can sense the changed data and obtain the data before the change.
4
5In terms of design, the code of V1 and V2 are expected to be completely isolated because V2 can do better than V1 in certain scenarios. However, from the actual perspective, the code developed in V1 have a solid foundation and it is not practical to migrate the entire code to V2 at a time. Therefore, it is allowed to use some capabilities of V2 in the code of V1 and capabilities of V1 is not completely prohibited in V2. For example, a custom component of V1 uses a custom component of V2, or V1 uses a decorator of V2. In this way, a problem of mixed use of V1 and V2 occurs.
6
7This document describes the mixed use of V1 and V2, aiming at guiding you to migrate code of V1 to V2.
8
9> **NOTE**
10>
11> State management V2 is supported since API version 12.
12
13## Overview
14
15The rules for mixing the use of V1 and V2 are as follows:
16
17* The decorators of V2 cannot be used in the custom components of V1. Otherwise, an error is reported during compilation.
18
19* When no variable is passed between components, custom components of V1 can use custom components of V2 as well as import \@ComponentV2 decorated custom components of a third party.
20
21* When variables are passed between components, such as passing variables of V1 to the custom components of V2, constraints are as follows:
22  - Variables that are not decorated by decorators in V1 (common variables) can be received only by using \@Param in V2.
23  - Variables decorated by the decorator in V1 (state variables) can be received only by using \@Param in V2 and are limited to simple data types such as boolean, number, enum, string, undefined and null.
24
25* The decorators of V1 cannot be used in the custom components of V2. Otherwise, an error is reported during compilation.
26
27* When no variable is passed between components, custom components of V2 can use custom components of V1 as well as import \@Component decorated custom components of a third party.
28
29* When variables are passed between components, such as passing variables of V2 to the custom components of V1, constraints are as follows:
30  - Variables that are not decorated by decorators in V2 (common variables) can be received by using \@State, \@Prop, and \@Provide in V1.
31  - Variables decorated by the decorator in V2 (state variables) of the built-in types, such as Array, Set, Map, and Date, are not supported in V1.
32
33## State Management Decorator Overview
34
35### Decorators of V1
36
37|  Type |                            Decorator                           |
38| :----------: | :----------------------------------------------------------: |
39| Intra-component decorator| \@State, \@Prop, \@Link, \@ObjectLink, \@Provide, \@Consume, \@StorageProp, \@StorageLink, \@LocalStorageProp, \@LocalStorageLink, \@Watch|
40| Class-related decorator|                     \@Observed, \@Track                     |
41
42### Decorators of V2
43
44|  Type |                            Decorator                           |
45| :----------: | :----------------------------------------------------------: |
46| Intra-component decorator| \@Local, \@Param, \@Provider, \@Consumer, \@Once, \@Event, \@Monitor, \@Computed|
47| Class-related decorator|                \@ObservedV2, \@Trace, \@Type                |
48
49### Data Types Supported by State Management Decorators
50
51
52
53| Type    | Keyword                                            |
54| ------------ | -------------------------------------------------- |
55| Simple type| boolean, number, enum, string, null, undefined    |
56| Function type| function (supported only by \@Event, \@Monitor, and \@Computed of V2)|
57| Object type  | Object                                             |
58| Class type   | Class                                              |
59| Built-in type    | Array, Map, Set, Date                             |
60
61
62
63## Constraints
64
65### Mixing Use of Decorators of V1 and V2 Is Forbidden
66
67**1. The decorators of V2 cannot be used in the custom components of V1.**
68
69```typescript
70@Component
71struct Child {
72  // @Param cannot be used in @Component. Otherwise, an error is reported during compilation.
73  // @Once and @Require are the extended decorators of @Param and must be used together with @Param.
74  @Param message: string = "";
75  @Event changeMessage: (val: string) => void;  // @Event cannot be used in @Component. Otherwise, an error is reported during compilation.
76
77  build() {
78    Column() {
79      Text(this.message)
80        .fontSize(50)
81        .fontWeight(FontWeight.Bold)
82        .onClick(() => {
83          this.changeMessage('world hello');
84        })
85    }
86  }
87}
88
89@Entry
90@Component
91struct Index {
92  @Local message: string ='Hello World'; // @Local cannot be used in @Component. Otherwise, an error is reported during compilation.
93
94  build() {
95    Column() {
96      Text(this.message)
97        .fontSize(50)
98        .fontWeight(FontWeight.Bold)
99      Divider()
100        .color(Color.Blue)
101      Child({
102        message: this.message,
103        changeMessage: (val: string) => {
104          this.message = val;
105        }
106      })
107    }
108    .height('100%')
109    .width('100%')
110  }
111}
112```
113
114The intra-component decorators in V2 cannot be used in the custom components of V1. Otherwise, an error is reported during compilation.
115
116The sample code shows how \@Local, \@Param, \@Event, \@Provider, \@Consumer, \@Monitor and \@Computed decorators work.
117
118**2. The decorators of V1 cannot be used in the custom components of V2.**
119
120```typescript
121@ComponentV2
122struct Child {
123  @Prop message: string = "";  	// @Prop cannot be used in @ComponentV2. Otherwise, an error is reported during compilation.
124  @Link myId: number;           // @Link cannot be used in @ComponentV2. Otherwise, an error is reported during compilation.
125
126  build() {
127    Column() {
128      Text(this.message)
129        .fontSize(50)
130        .fontWeight(FontWeight.Bold)
131        .onClick(() => {
132          this.message = 'world hello';
133        })
134      Divider()
135        .color(Color.Blue)
136      Text(`${this.myId}`)
137        .id('HelloWorld')
138        .fontSize(50)
139        .fontWeight(FontWeight.Bold)
140        .onClick(() => {
141          this.myId++;
142        })
143    }
144  }
145}
146
147@Entry
148@ComponentV2
149struct Index {
150  @State message: string = 'Hello World';      // @State cannot be used in @ComponentV2. Otherwise, an error is reported during compilation.
151  @State @Watch('idChange') myId: number = 1;  // @Watch cannot be used in @ComponentV2. Otherwise, an error is reported during compilation.
152
153  idChange(propName: number) : void {
154    console.info(`id changed ${this.myId}`);
155  }
156
157  build() {
158    Column() {
159      Text(this.message)
160        .fontSize(50)
161        .fontWeight(FontWeight.Bold)
162      Divider()
163        .color(Color.Blue)
164      Child({
165        message: this.message,
166        myId: this.myId
167      })
168    }
169    .height('100%')
170    .width('100%')
171    .margin(5)
172  }
173}
174```
175
176The intra-component decorators in V1 cannot be used in the custom components of V2. Otherwise, an error is reported during compilation.
177
178The sample code shows how \@ObjectLink, \@Provide, \@Consume, \@StorageProp, \@StorageLink, \@LocalStorageProp, and \@LocalStorageLink decorators work.
179
180### Using Multiple Decorators to Decorate the Same Variable Is Forbidden (Except \@Watch, \@Once, and \@Require)
181
182```typescript
183@Component
184struct Child {
185  @State @Prop message: string = "";	// Multiple decorators of V1 cannot decorate the same variable. Otherwise, an error is reported during compilation.
186
187  build() {
188    Column() {
189      Text(this.message)
190        .fontSize(50)
191        .fontWeight(FontWeight.Bold)
192        .onClick(() => {
193          this.message = 'world hello';
194        })
195    }
196  }
197}
198
199@Entry
200@ComponentV2
201struct Index {
202  @Local @Param message: string = 'Hello World'; // Multiple decorators of V2 cannot decorate the same variable. Otherwise, an error is reported during compilation.
203
204  build() {
205    Column() {
206      Text(this.message)
207        .fontSize(50)
208        .fontWeight(FontWeight.Bold)
209      Divider()
210        .color(Color.Blue)
211      Child({
212        message: this.message
213      })
214    }
215    .height('100%')
216    .width('100%')
217  }
218}
219```
220
221All decorators cannot decorate the same variable except extended decorators \@Watch, \@Once, and \@Require that can be used with other decorators.
222
223## Introduction to Mixed Use
224
225### Mixing Use of Decorators of V1 and V2
226
227**1. Use the \@ObservedV2 decorated class object in a custom component of V1.**
228
229```typescript
230@ObservedV2
231class Info {
232  @Trace myId: number;   		// Observable.
233  name: string;           		// Not observable.
234  @Track trackId: number = 1; 	// As a decorator of V1, @Track cannot be used in @ObservedV2. Otherwise, an error is reported during compilation. Remove @Track to eliminate the error.
235
236  constructor(id?: number, name?: string) {
237    this.myId = id || 0;
238    this.name = name || 'aaa';
239  }
240}
241
242@Observed
243class message extends Info {	// Classes inherited from @ObservedV2 cannot be decorated by Observed. Otherwise, an error is reported during compilation. Remove @Observed to eliminate the error.
244}
245
246class MessageInfo extends Info {
247}
248
249@Entry
250@Component
251struct Index {
252  info1: Info = new Info();                      // @ObservedV2 decorated class can be used in V1, and @Trace decorated class is observable.
253  @State info2: Info = new Info();               // @ObservedV2 decorated class cannot be decorated by the decorator of V1. Otherwise, an error is reported during compilation. Remove @State to eliminate the error.
254
255  @State messageInfo: MessageInfo = new MessageInfo();  // Classes inherited from @ObservedV2 cannot be decorated by the decorator of V1. Otherwise, an error is reported during runtime. Remove @State to eliminate the error.
256  build() {
257    Column() {
258      Text(`info1 name: ${this.info1.name}`)            // name is not decorated by @Trace and is not observable.
259        .fontSize(50)
260        .fontWeight(FontWeight.Bold)
261        .onClick(() => {
262          this.info1.name += 'b';
263        })
264      Text(`info1 id: ${this.info1.myId}`)              // myId is decorated by @Trace and is observable.
265        .fontSize(50)
266        .fontWeight(FontWeight.Bold)
267        .onClick(() => {
268          this.info1.myId += 1;
269        })
270      Divider()
271        .color(Color.Blue)
272      Text(`info2 id: ${this.info2.myId}`)
273        .fontSize(50)
274        .fontWeight(FontWeight.Bold)
275        .onClick(() => {
276          this.info2.myId += 1;
277        })
278      Divider()
279        .color(Color.Blue)
280      Text(`messageInfo id: ${this.messageInfo.myId}`) // A crash occurs during runtime when the class inherited from @ObservedV2 is decorated by the decorators of V1. Remove @State to eliminate the error.
281        .fontSize(50)
282        .fontWeight(FontWeight.Bold)
283        .onClick(() => {
284          this.messageInfo.myId += 1;
285        })
286    }
287    .height('100%')
288    .width('100%')
289    .margin(5)
290  }
291}
292```
293
294Using \@ObservedV2 must comply with the following rules:
295
296* \@ObservedV2 can decorate only Class; \@Trace and \@Type can decorate only class properties and can be used only in \@ObservedV2.
297* \@Track cannot be used in \@ObservedV2.
298* A class decorated by \@ObservedV2 cannot be directly decorated by the decorator of V1. Otherwise, an error is reported during compilation.
299* In the example, the code can be executed properly after you remove the decorator that reports error. The property change can be observed only when the class is decorated by \@Trace.
300
301**2. Use the \@Observed decorated class object in a custom component of V2.**
302
303```typescript
304@Observed
305class Info {
306  @Track myId: number;   		  // Not observable. Only associated update caused by other property changes can be prevented.
307  name: string;           		  // Not observable.
308  @Trace trackId: number = 1; 	  // As a decorator of V2, @Trace cannot be used in @Observed. Otherwise, an error is reported during compilation. Remove @Trace to eliminate the error.
309  constructor(id?: number, name?: string) {
310    this.myId = id || 0;
311    this.name = name || 'aaa';
312  }
313}
314
315@ObservedV2
316class message extends Info {      // @ObservedV2 decorated class cannot inherit from @Observed. Otherwise, an error is reported during compilation. Remove @ObservedV2 to eliminate the error.
317}
318
319class MessageInfo extends Info {
320}
321
322@Entry
323@ComponentV2
324struct Index {
325  info1: Info = new Info();             // @Observed decorated class can be used in V2.
326  @Local info2: Info = new Info();      // @Observe decorated class cannot be decorated by the decorator of V2. Otherwise, an error is reported during compilation. Remove @Local to eliminate the error.
327  @Local messageInfo: MessageInfo = new MessageInfo();
328  build() {
329    Column() {
330      Text(`info1 name: ${this.info1.name}`)
331        .fontSize(50)
332        .fontWeight(FontWeight.Bold)
333        .onClick(() => {
334          this.info1.name += 'b';
335        })
336      Text(`info1 id: ${this.info1.myId}`)
337        .fontSize(50)
338        .fontWeight(FontWeight.Bold)
339        .onClick(() => {
340          this.info1.myId += 1;
341        })
342      Divider()
343        .color(Color.Blue)
344      Text(`info2 id: ${this.info2.myId}`)
345        .fontSize(50)
346        .fontWeight(FontWeight.Bold)
347        .onClick(() => {
348          this.info2.myId += 1;
349        })
350      Divider()
351        .color(Color.Blue)
352      // Classes inherited from @ObservedV2 are decorated by the decorator of V2, but the class properties cannot be observed by the decorator of V2. Therefore, you are not advised to use the @Observed decorated classes in V2.
353      Text(`messageInfo id: ${this.messageInfo.myId}`)
354        .fontSize(50)
355        .fontWeight(FontWeight.Bold)
356        .onClick(() => {
357          this.messageInfo.myId += 1;
358        })
359    }
360    .height('100%')
361    .width('100%')
362    .margin(5)
363  }
364}
365```
366
367You are not advised to use \@Observed decorated classes in V2 because \@Observed and \@Track decorated class properties can only be distinguished but not be observed. In-depth data can be observed only when \@Observed and \@ObjectLink are used to split nested data. However, \@ObjectLink cannot be used in custom components of V2.
368
369When migrating code from V1 to V2, you are not advised to use \@Observed decorated classes in \@ComponentV2 because they are not observable. If you have to use the classes, comply with the following rules:
370
371* \@Observed can only decorate class, and \@Trace cannot be used in \@Observed.
372* \@Observed and \@Track decorated classes are not observable and you can use the decorators only to prevent the entire class from being refreshed when a class property is changed.
373* Classes inherited from @Observed are decorated by the decorator of V2, but the class properties cannot be observed the intra-component decorator of V2. Therefore, class property changes cannot be observed using \@Observed.
374* In the example, the code can be executed properly after you remove the decorator that reports error. Because the observation capability is unavailable, you are not advised to use \@Observed in V2.
375
376### Mixing Use of Custom Components of V1 and V2 When No Variable Is Passed
377
378**1. Use the custom components of V2 in V1.**
379
380```typescript
381@ComponentV2
382struct Child {
383  @Local message: string = "hello";
384
385  build() {
386    Column() {
387      Text(this.message)
388        .fontSize(50)
389        .fontWeight(FontWeight.Bold)
390        .onClick(() => {
391          this.message = 'world';
392        })
393    }
394  }
395}
396
397@Entry
398@Component
399struct Index {
400  @State message: string = 'Hello World';
401
402  build() {
403    Column() {
404      Text(this.message)
405        .fontSize(50)
406        .fontWeight(FontWeight.Bold)
407        .onClick(() => {
408          this.message = 'world hello';
409        })
410      Divider()
411        .color(Color.Blue)
412      Child()
413    }
414    .height('100%')
415    .width('100%')
416  }
417}
418```
419
420Using the custom components of V2 in V1 performs no impact when no variable is passed.
421
422**2. Use the custom components of V1 in V2.**
423
424```typescript
425@Component
426struct Child {
427  @State message: string = "hello";
428
429  build() {
430    Column() {
431      Text(this.message)
432        .fontSize(50)
433        .fontWeight(FontWeight.Bold)
434        .onClick(() => {
435          this.message = 'world';
436        })
437    }
438  }
439}
440
441@Entry
442@ComponentV2
443struct Index {
444  @Local message: string = 'Hello World';
445
446  build() {
447    Column() {
448      Text(this.message)
449        .fontSize(50)
450        .fontWeight(FontWeight.Bold)
451        .onClick(() => {
452          this.message = 'world hello';
453        })
454      Divider()
455        .color(Color.Blue)
456      Child()
457    }
458    .height('100%')
459    .width('100%')
460  }
461}
462```
463
464Using the custom components of V1 in V2 performs no impact when no variable is passed.
465
466### Mixing Use of Custom Components of V1 and V2 When Variables Are Passed
467
468**1. V1 > V2: Pass the common variables of V1 to the custom component of V2.**
469
470```typescript
471class Info {
472  myId: number;
473  name: string;
474
475  constructor(myId?: number, name?: string) {
476    this.myId = myId || 0;
477    this.name = name || 'aaa';
478  }
479}
480
481@ComponentV2
482struct Child {
483  // V2 strictly manages data input. When receiving data from the parent component, the @Param decorator must be used to receive data.
484  @Param @Once message: string = "hello";	              // Changes are observable and can be synchronized to the parent component through @Event. @Once can be used to change @Param decorated variables.
485  @Param @Once undefineVal: string | undefined = undefined;  // @Once can be used to change @Param decorated variables.
486  @Param info: Info = new Info();		                 // The class property changes are not observable.
487  @Require @Param set: Set<number>;
488
489  build() {
490    Column() {
491      Text(`child message:${this.message}`) // Display the string.
492        .fontSize(30)
493        .fontWeight(FontWeight.Bold)
494        .onClick(() => {
495          this.message = 'world';
496        })
497
498      Divider()
499        .color(Color.Blue)
500      Text ('undefineVal:${this.undefineVal}') // Display undefineVal.
501        .fontSize(30)
502        .fontWeight(FontWeight.Bold)
503        .onClick(() => {
504          this.undefineVal = "change to define";
505        })
506      Divider()
507        .color(Color.Blue)
508      Text ('info id:${this.info.myId}') // Display info:myId.
509        .fontSize(30)
510        .fontWeight(FontWeight.Bold)
511        .onClick(() => {
512          this.info.myId++;
513        })
514      Divider()
515        .color(Color.Blue)
516      ForEach(Array.from(this.set.values()), (item: number) => { // Display set.
517        Text(`${item}`)
518          .fontSize(30)
519      })
520    }
521    .margin(5)
522  }
523}
524
525@Entry
526@Component
527struct Index {
528  message: string = 'Hello World';       // Simple type.
529  undefineVal: undefined = undefined;    // Simple type: undefined.
530  info: Info = new Info();               // Class type.
531  set: Set<number> = new Set([10, 20]);  // Built-in type.
532
533  build() {
534    Column() {
535      Text(`message:${this.message}`)
536        .fontSize(30)
537        .fontWeight(FontWeight.Bold)
538        .onClick(() => {
539          this.message = 'world hello';
540        })
541      Divider()
542        .color(Color.Blue)
543      Child({
544        message: this.message,
545        undefineVal: this.undefineVal,
546        info: this.info,
547        set: this.set
548      })
549    }
550    .height('100%')
551    .width('100%')
552  }
553}
554```
555
556When the common variables of V1 are passed to a custom component of V2, constraints are as follows:
557
558* The custom component of V2 must receive data through \@Param.
559* To observe the received data changes, use \@Param; to observe the received class changes, use \@ObservedV2 and \@Trace.
560
561**2. V1 > V2: Pass the state variables of V1 to the custom component of V2.**
562
563```typescript
564class Info {
565  myId: number;
566  name: string;
567
568  constructor(myId?: number, name?: string) {
569    this.myId = myId || 0;
570    this.name = name || 'aaa';
571  }
572}
573
574@ComponentV2
575struct Child {
576  // V2 strictly manages data input. When receiving data from the parent component, the @Param decorator must be used to receive data.
577  @Param @Once message: string = "hello";
578  @Param @Once undefineVal: string | undefined = undefined;  // @Once can be used to change @Param decorated variables.
579  @Param info: Info = new Info();
580  @Require @Param set: Set<number>;
581  build() {
582    Column() {
583      Text(`child message:${this.message}`) // Display the string.
584        .fontSize(30)
585        .fontWeight(FontWeight.Bold)
586        .onClick(() => {
587          this.message = 'world';
588        })
589      Divider()
590        .color(Color.Blue)
591      Text ('undefineVal:${this.undefineVal}') // Display undefineVal.
592        .fontSize(30)
593        .fontWeight(FontWeight.Bold)
594        .onClick(() => {
595          this.undefineVal = "change to define";
596        })
597      Divider()
598        .color(Color.Blue)
599      Text ('info id:${this.info.myId}') // Display info:myId.
600        .fontSize(30)
601        .fontWeight(FontWeight.Bold)
602        .onClick(() => {
603          this.info.myId++;
604        })
605      Divider()
606        .color(Color.Blue)
607      ForEach(Array.from(this.set.values()), (item: number) => { // Display set.
608        Text(`${item}`)
609          .fontSize(30)
610      })
611    }
612    .margin(5)
613  }
614}
615
616@Entry
617@Component
618struct Index {
619  @State message: string = 'Hello World';       // Simple type data can be passed.
620  @State undefineVal: undefined = undefined;    // Simple type data, undefined, can be passed.
621  @State info: Info = new Info();               // Class type cannot be passed. Otherwise, an error is reported during compilation. Remove @State to eliminate the error.
622  @State set: Set<number> = new Set([10, 20]);  // Built-in type cannot be passed. Otherwise, an error is reported during compilation. Remove @State to eliminate the error.
623
624  build() {
625    Column() {
626      Text(`message:${this.message}`)
627        .fontSize(30)
628        .fontWeight(FontWeight.Bold)
629        .onClick(() => {
630          this.message = 'world hello';
631        })
632      Divider()
633        .color(Color.Blue)
634      Child({
635        message: this.message,
636        undefineVal: this.undefineVal,
637        info: this.info,
638        set: this.set
639      })
640    }
641    .height('100%')
642    .width('100%')
643  }
644}
645```
646
647When the state variable of V1 is assigned to the custom component of V2, rules are as follows:
648
649* Only simple variables are supported. For other types of data, an error is reported during compilation.
650
651* In the example, the \@State decorator is used. Other decorators such as \@Prop, \@Link, \@ObjectLink, \@Provide, \@Consume, \@StorageProp, \@StorageLink, \@LocalStorageProp and \@LocalStorageLink work in the same way as \@State.
652
653**3. V2 > V1: Pass the common variables of V2 to the custom component of V1.**
654
655```typescript
656class Info {
657  myId: number;
658  name: string;
659
660  constructor(myId?: number, name?: string) {
661    this.myId = myId || 0;
662    this.name = name || 'aaa';
663  }
664}
665
666@Component
667struct Child {
668  // State variable received by V1 from V2. Only @State, @Prop, and @Provide decorators can be used.
669  @State  message: string = "hello";	         // Changes are observable.
670  @State info: Info = new Info();		      	// Top-level class property changes are observable.
671  @Prop undefineVal: undefined | string = undefined;
672  @Provide setMap: Set<number> = new Set();
673  build() {
674    Column() {
675      Text(`child message:${this.message}`) 	// Display the string.
676        .fontSize(30)
677        .fontWeight(FontWeight.Bold)
678        .onClick(() => {
679          this.message = 'world';
680        })
681      Divider()
682        .color(Color.Blue)
683      Text(`undefineVal:${this.undefineVal}`) 	// Display undefineVal.
684        .fontSize(30)
685        .fontWeight(FontWeight.Bold)
686        .onClick(() => {
687          this.undefineVal = "change to define";
688        })
689      Divider()
690        .color(Color.Blue)
691      Text(`info id:${this.info.myId}`)		 	// Display info:myId.
692        .fontSize(30)
693        .fontWeight(FontWeight.Bold)
694        .onClick(() => {
695          this.info.myId++;
696        })
697      Divider()
698        .color(Color.Blue)
699      ForEach(Array.from(this.setMap.values()), (item: number) => {  // Display set.
700        Text(`${item}`)
701          .fontSize(30)
702      })
703    }
704    .margin(5)
705  }
706}
707
708@Entry
709@ComponentV2
710struct Index {
711  message: string = 'Hello World';       // Simple type.
712  undefineVal: undefined = undefined;    // Simple type: undefined.
713  info: Info = new Info();               // Class type.
714  set: Set<number> = new Set([10, 20]);  // Built-in type.
715
716  build() {
717    Column() {
718      Text(`message:${this.message}`)
719        .fontSize(30)
720        .fontWeight(FontWeight.Bold)
721        .onClick(() => {
722          this.message = 'world hello';
723        })
724      Divider()
725        .color(Color.Blue)
726      Child({
727        message: this.message,
728        undefineVal: this.undefineVal,
729        info: this.info,
730        setMap: this.set
731      })
732    }
733    .height('100%')
734    .width('100%')
735  }
736}
737```
738
739When a common variable of V2 is passed to a custom component of V1:
740
741* V1 can receive data without using the decorator. The received variables are also common variables in the custom component of V1.
742
743* If V1 uses a decorator to receive data, data can be received only through \@State, \@Prop, and \@Provide.
744
745**4. V2 > V1: Pass the state variables of V2 to the custom component of V1.**
746
747```typescript
748class Info {
749  myId: number;
750  name: string;
751
752  constructor(myId?: number, name?: string) {
753    this.myId = myId || 0;
754    this.name = name || 'aaa';
755  }
756}
757
758@Component
759struct Child {
760  // State variable received by V1 from V2. Only @State, @Prop, and @Provide can be used.
761  @State  message: string = "hello";	        // Changes are observable.
762  @State info: Info = new Info();		        // Top-level class property changes are observable.
763  @Prop undefineVal: undefined | string = undefined;
764  @Provide set: Set<number> = new Set();
765  build() {
766    Column() {
767      Text(`child message:${this.message}`) 	// Display the string.
768        .fontSize(30)
769        .fontWeight(FontWeight.Bold)
770        .onClick(() => {
771          this.message = 'world';
772        })
773      Divider()
774        .color(Color.Blue)
775      Text(`undefineVal:${this.undefineVal}`) 	// Display undefineVal.
776        .fontSize(30)
777        .fontWeight(FontWeight.Bold)
778        .onClick(() => {
779          this.undefineVal = "change to define";
780        })
781      Divider()
782        .color(Color.Blue)
783      Text(`info id:${this.info.myId}`) 	// Display info:myId.
784        .fontSize(30)
785        .fontWeight(FontWeight.Bold)
786        .onClick(() => {
787          this.info.myId++;
788        })
789
790      Divider()
791        .color(Color.Blue)
792      ForEach(Array.from(this.set.values()), (item: number) => {  // Display set.
793        Text(`${item}`)
794          .fontSize(30)
795      })
796    }
797    .margin(5)
798  }
799}
800
801@Entry
802@ComponentV2
803struct Index {
804  @Local message: string = 'Hello World';       	// Simple type data can be passed.
805  @Provider() undefineVal: undefined = undefined;   // Simple type data, undefined, can be passed.
806  @Consumer() info: Info = new Info();          	// Class type can be passed.
807  @Param set: Set<number> = new Set([10, 20]);  	// Built-in type cannot be passed. Otherwise, an error is reported during compilation. Remove @Param to eliminate the error.
808
809  build() {
810    Column() {
811      Text(`message:${this.message}`)
812        .fontSize(30)
813        .fontWeight(FontWeight.Bold)
814        .onClick(() => {
815          this.message = 'world hello';
816        })
817
818      Divider()
819        .color(Color.Blue)
820      Child({
821        message: this.message,
822        undefineVal: this.undefineVal,
823        info: this.info,
824        set: this.set
825      })
826    }
827    .height('100%')
828    .width('100%')
829  }
830}
831```
832
833When the state variables of V2 are passed to a custom component of V1, constraints are as follows:
834
835* V1 can receive data without using the decorator. The received variables are also common variables in the custom component of V1.
836
837* If V1 uses a decorator to receive data, data can be received only through \@State, \@Prop, and \@Provide.
838* If a decorator is used to receive data in V1, data of the built-in type cannot be received.
839
840### Summary
841
842According to the detailed analysis of the mixed use of V1 and V2, when the code of V1 is used in V2, that is, components or classes of V1 are passed to V2, most capabilities of V1 are disabled in V2. When the code of V2 is used in V1, that is, components or classes of V2 are passed to V1, some functions are available, for example, \@ObservedV2 and \@Trace. This is also the most helpful way to observe the V1 nested class data. Therefore, during code development, you are not advised to use V1 and V2 together for mixed development. However, you can gradually migrate the code of V1 to V2 to steadily replace the function code of V1. In addition, you are not advised to use the code of V1 in V2.
843
844## Supplementary Scenarios
845
846Classes can be nested at multiple levels because they are decorated by \@Observed and \@ObservedV2, leading to a complex scenario. This section mainly describes the self-nesting of the class type and the nesting of the built-in type. Lack of in-depth observation capability like \@ObservedV2 and @Trace, the in-depth nesting of \@Observed is not discussed. Only the use scenarios of \@ObservedV2 in V1 are discussed.
847
848### Using \@Observed and \@ObjectLink to Observe Nested Classes
849
850```typescript
851@Observed
852class Info {
853  myId: number;
854  name: string;
855
856  constructor(myId?: number, name?: string) {
857    this.myId = myId || 0;
858    this.name = name || 'aaa';
859  }
860}
861
862@Observed
863class MessageInfo { 		// One-level nesting.
864  @Track info: Info;        // Prevent the info from being updated when the messageId is changed.
865  @Track messageId: number; // Prevent the info from being updated when the messageId is changed.
866
867  constructor(info?: Info, messageId?: number) {
868    this.info = info || new Info();
869    this.messageId = messageId || 0;
870  }
871}
872
873@Observed
874class MessageInfoNested { // Dual-level nesting.
875  messageInfo: MessageInfo;
876
877  constructor(messageInfo?: MessageInfo) {
878    this.messageInfo = messageInfo || new MessageInfo();
879  }
880}
881
882@Component
883struct GrandSon {
884  @ObjectLink info: Info;
885
886  build() {
887    Column() {
888      Text ('ObjectLink info info.myId:${this.info.myId}') // After @ObjectLink disassembles the level twice, the change is observable.
889        .fontSize(30)
890        .onClick(() => {
891          this.info.myId++;
892        })
893    }
894  }
895}
896
897@Component
898struct Child {
899  @ObjectLink messageInfo: MessageInfo;
900
901  build() {
902    Column() {
903      Text(`ObjectLink MessageInfo messageId:${this.messageInfo.messageId}`)  // After @ObjectLink disassembles the levels, the change of the top-level class property is observable.
904        .fontSize(30)
905        .onClick(() => {
906          this.messageInfo.messageId++;
907        })
908      Divider()
909        .color(Color.Blue)
910      Text(`ObjectLink MessageInfo info.myId:${this.messageInfo.info.myId}`)  // After @ObjectLink disassembles the level, the change is not observable.
911        .fontSize(30)
912        .onClick(() => {
913          this.messageInfo.info.myId++;
914        })
915      GrandSon({info: this.messageInfo.info});				// Continue to disassemble the top-level child components.
916    }
917  }
918}
919
920
921
922@Entry
923@Component
924struct Index {
925  @State messageInfoNested: MessageInfoNested = new MessageInfoNested();  // For the data nested at three levels, you need to observe all data.
926
927  build() {
928    Column() {
929      // Observe messageInfoNested.
930      Text(`messageInfoNested messageId:${this.messageInfoNested.messageInfo.messageId}`)  // @State can only observe the top-level class properties but not their changes.
931        .fontSize(30)
932        .onClick(() => {
933          this.messageInfoNested.messageInfo.messageId++;
934        })
935      Divider()
936        .color(Color.Blue)
937      // Observe messageInfoId through @ObjectLink.
938      Child({messageInfo: this.messageInfoNested.messageInfo})      // After disassembling, you can use @ObjectLink to observe the lower-level changes.
939      Divider()
940        .color(Color.Blue)
941    }
942    .height('100%')
943    .width('100%')
944    .margin(10)
945  }
946}
947```
948
949The sample code uses a three-layer nesting to show:
950
951* The observation capability of the decorator of V1 is to function as a proxy for data. Therefore, when data is nested, the decorator of V1 can only disassemble the child component to observe lower-level data through \@Observed and \@ObjectLink.
952* \@Track is used to prevent the **info** in the **MessageInfo** class from being updated when the **messageId** is changed. You can remove \@Track to observe the change. When the **messageId** is changed, the **info** is also changed. However, this change cannot be observed by \@ObjectLink.
953
954### Using @ObsevedV2 and @Trace to Observe Nested Classes
955
956```typescript
957@ObservedV2
958class Info {
959  @Trace myId: number;
960  name: string;
961
962  constructor(myId?: number, name?: string) {
963    this.myId = myId || 0;
964    this.name = name || 'aaa';
965  }
966}
967
968@Observed
969class MessageInfo { // One-level nesting.
970  @Track info: Info;        // Prevent the info from being updated when the messageId is changed.
971  @Track messageId: number; // Prevent the info from being updated when the messageId is changed.
972
973  constructor(info?: Info, messageId?: number) {
974    this.info = info || new Info();   // Use the input info or create an Info.
975    this.messageId = messageId || 0;
976  }
977}
978
979@Observed
980class MessageInfoNested { // Dual-level nesting. If MessageInfoNested is decorated by @ObservedV2, it cannot be decorated by the state variable decorator of V1, such as @State.
981  messageInfo: MessageInfo;
982
983  constructor(messageInfo?: MessageInfo) {
984    this.messageInfo = messageInfo || new MessageInfo();
985  }
986}
987
988@Component
989struct Child {
990  @ObjectLink messageInfo: MessageInfo;
991
992  build() {
993    Column() {
994      Text(`ObjectLink MessageInfo messageId:${this.messageInfo.messageId}`)  // After @ObjectLink disassembles the levels, the change of the top-level class property is observable.
995        .fontSize(30)
996        .onClick(() => {
997          this.messageInfo.messageId++;
998        })
999    }
1000  }
1001}
1002
1003@Entry
1004@Component
1005struct Index {
1006  @State messageInfoNested: MessageInfoNested = new MessageInfoNested();  // For the data nested at three levels, you need to observe the internal data.
1007
1008  build() {
1009    Column() {
1010      // Observe messageInfoNested. @State can only observe the top-level data and cannot observe the changes.
1011      Text(`messageInfoNested messageId:${this.messageInfoNested.messageInfo.messageId}`)
1012        .fontSize(30)
1013        .onClick(() => {
1014          this.messageInfoNested.messageInfo.messageId++;
1015        })
1016      Divider()
1017        .color(Color.Blue)
1018      Text(`messageInfoNested name:${this.messageInfoNested.messageInfo.info.name}`)   //  Being not decorated by @Trace, it is not observable.
1019        .fontSize(30)
1020        .onClick(() => {
1021          this.messageInfoNested.messageInfo.info.name += 'a';
1022        })
1023      Divider()
1024        .color(Color.Blue)
1025      Text(`messageInfoNested myId:${this.messageInfoNested.messageInfo.info.myId}`) // Decorated by @Trace, data changes can be observed no matter how many levels data is nested in.
1026        .fontSize(30)
1027        .onClick(() => {
1028          this.messageInfoNested.messageInfo.info.myId++;
1029        })
1030      Divider()
1031        .color(Color.Blue)
1032      // Observe messageInfoId through @ObjectLink.
1033      Child({messageInfo: this.messageInfoNested.messageInfo})      // After disassembling, you can use @ObjectLink to observe the lower-level changes.
1034    }
1035    .height('100%')
1036    .width('100%')
1037    .margin(10)
1038  }
1039}
1040```
1041
1042The sample code shows:
1043
1044* \@observedV2 and \@Trace nest the observation capability to the class properties. Therefore, when a class property is marked by @Trace, the change can be observed regardless of the number of nested levels.
1045* When \@ObservdV2 and \@Observed are used together, the decorator used by the outermost class determines whether the class object can be decorated by the decorator of V1. For example, the class decorated by \@ObservedV2 in the lower level does not affect the outermost class decorated by the decorator of V1.
1046