• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# \@Link: Two-Way Synchronization Between Parent and Child Components
2
3
4An \@Link decorated variable can create two-way synchronization with a variable of its parent component.
5
6
7> **NOTE**
8>
9> Since API version 9, this decorator is supported in ArkTS widgets.
10
11
12## Overview
13
14An \@Link decorated variable in a child component shares the same value with a variable in its parent component.
15
16
17## Rules of Use
18
19| \@Link Decorator| Description                                      |
20| ----------- | ---------------------------------------- |
21| Decorator parameters      | None.                                       |
22| Synchronization type       | Two-way:<br>from an \@State, \@StorageLink, or \@Link decorated variable in the parent component to this variable; and the other way around.|
23| Allowed variable types  | Object, class, string, number, Boolean, enum, and array of these types. For details about the scenarios of nested types, see [Observed Changes](#observed-changes).<br>The type must be specified and must be the same as that of the counterpart variable of the parent component.<br>**any** is not supported. A combination of simple and complex types is not supported. The **undefined** and **null** values are not allowed.<br>**NOTE**<br>The Length, ResourceStr, and ResourceColor types are a combination of simple and complex types and therefore not supported.|
24| Initial value for the decorated variable  | Forbidden.                              |
25
26
27## Variable Transfer/Access Rules
28
29| Transfer/Access     | Description                                      |
30| ---------- | ---------------------------------------- |
31| Initialization and update from the parent component| Mandatory. A two-way synchronization relationship can be established with the @State, @StorageLink, or \@Link decorated variable in the parent component. An \@Link decorated variable can be initialized from an \@State, \@Link, \@Prop, \@Provide, \@Consume, \@ObjectLink, \@StorageLink, \@StorageProp, \@LocalStorageLink, or \@LocalStorageProp decorated variable in the parent component.<br>Since API version 9, the syntax is **Comp({&nbsp;aLink:&nbsp;this.aState&nbsp;})** for initializing an \@Link decorated variable in the child component from an @State decorated variable in its parent component. The **Comp({aLink:&nbsp;$aState})** syntax is also supported|
32| Subnode initialization  | Supported; can be used to initialize a regular variable or \@State, \@Link, \@Prop, or \@Provide decorated variable in the child component.|
33| Access | Private, accessible only within the component.                          |
34
35  **Figure 1** Initialization rule
36
37![en-us_image_0000001502092556](figures/en-us_image_0000001502092556.png)
38
39
40## Observed Changes and Behavior
41
42
43### Observed Changes
44
45- When the decorated variable is of the Boolean, string, or number type, its value change can be observed. For details, see [Example for @Link with Simple and Class Types](#example-for-link-with-simple-and-class-types).
46
47- When the decorated variable is of the class or Object type, its value change and value changes of all its attributes, that is, the attributes that **Object.keys(observedObject)** returns. For details, see [Example for @Link with Simple and Class Types](#example-for-link-with-simple-and-class-types).
48
49- When the decorated variable is of the array type, the addition, deletion, and updates of array items can be observed. For details, see [Array Type \@Link](#array-type-link).
50
51
52### Framework Behavior
53
54An \@Link decorated variable shares the lifecycle of its owning component.
55
56To understand the value initialization and update mechanism of the \@Link decorated variable, it is necessary to consider the parent component and the initial render and update process of the child component that owns the \@Link decorated variable (in this example, the \@State decorated variable in the parent component is used).
57
581. Initial render: The execution of the parent component's **build()** function creates a new instance of the child component. The initialization process is as follows:
59   1. An \@State decorated variable of the parent component must be specified to initialize the child component's \@Link decorated variable. The child component's \@Link decorated variable value and its source variable are kept in sync (two-way data synchronization).
60   2. The \@State state variable wrapper class of the parent component is passed to the child component through the build function. After obtaining the \@State state variable of the parent component, the \@Link wrapper class of the child component registers the **this** pointer to the current \@Link wrapper class with the \@State variable of the parent component.
61
622. Update of the \@Link source: When the state variable in the parent component is updated, the \@Link decorated variable in the related child component is updated. Processing steps:
63   1. As indicated in the initial rendering step, the child component's \@Link wrapper class registers the current **this** pointer with the parent component. When the \@State decorated variable in the parent component is changed, all system components (**elementid**) and state variables (such as the \@Link wrapper class) that depend on the parent component are traversed and updated.
64   2. After the \@Link wrapper class is updated, all system components (**elementId**) that depend on the \@Link decorated variable in the child component are notified of the update. In this way, the parent component has the state data of the child components synchronized.
65
663. Update of \@Link: After the \@Link decorated variable in the child component is updated, the following steps are performed (the \@State decorated variable in the parent component is used):
67   1. After the \@Link decorated variable is updated, the **set** method of the \@State wrapper class in the parent component is called to synchronize the updated value back to the parent component.
68   2. The \@Link in the child component and \@State in the parent component traverse the dependent system components and update the corresponding UI. In this way, the \@Link decorated variable in the child component is synchronized back to the \@State decorated variable in the parent component.
69
70
71## Application Scenarios
72
73
74### Example for @Link with Simple and Class Types
75
76The following example is for \@Link of both the simple type and class type. After **Parent View: Set yellowButton** and **Parent View: Set GreenButton** in the parent component **ShufflingContainer** are clicked, the change in the parent component is synchronized to the child components. The change of the \@Link decorated variable in the child components **GreenButton** and **YellowButton** is also synchronized to the parent component.
77
78
79```ts
80class GreenButtonState {
81  width: number = 0;
82  constructor(width: number) {
83    this.width = width;
84  }
85}
86@Component
87struct GreenButton {
88  @Link greenButtonState: GreenButtonState;
89  build() {
90    Button('Green Button')
91      .width(this.greenButtonState.width)
92      .height(150.0)
93      .backgroundColor('#00ff00')
94      .onClick(() => {
95        if (this.greenButtonState.width < 700) {
96          // Update the attribute of the class. The change can be observed and synchronized back to the parent component.
97          this.greenButtonState.width += 125;
98        } else {
99          // Update the class. The change can be observed and synchronized back to the parent component.
100          this.greenButtonState = new GreenButtonState(100);
101        }
102      })
103  }
104}
105@Component
106struct YellowButton {
107  @Link yellowButtonState: number;
108  build() {
109    Button('Yellow Button')
110      .width(this.yellowButtonState)
111      .height(150.0)
112      .backgroundColor('#ffff00')
113      .onClick(() => {
114        // The change of the decorated variable of a simple type in the child component can be synchronized back to the parent component.
115        this.yellowButtonState += 50.0;
116      })
117  }
118}
119@Entry
120@Component
121struct ShufflingContainer {
122  @State greenButtonState: GreenButtonState = new GreenButtonState(300);
123  @State yellowButtonProp: number = 100;
124  build() {
125    Column() {
126      // Simple type @Link in the child component synchronized from @State in the parent component.
127      Button('Parent View: Set yellowButton')
128        .onClick(() => {
129          this.yellowButtonProp = (this.yellowButtonProp < 700) ? this.yellowButtonProp + 100 : 100;
130        })
131      // Class type @Link in the child component synchronized from @State in the parent component.
132      Button('Parent View: Set GreenButton')
133        .onClick(() => {
134          this.greenButtonState.width = (this.greenButtonState.width < 700) ? this.greenButtonState.width + 100 : 100;
135        })
136      // Initialize the class type @Link.
137      GreenButton({ greenButtonState: $greenButtonState })
138      // Initialize the simple type @Link.
139      YellowButton({ yellowButtonState: $yellowButtonProp })
140    }
141  }
142}
143```
144
145
146### Array Type \@Link
147
148
149```ts
150@Component
151struct Child {
152  @Link items: number[];
153
154  build() {
155    Column() {
156      Button(`Button1: push`).onClick(() => {
157        this.items.push(this.items.length + 1);
158      })
159      Button(`Button2: replace whole item`).onClick(() => {
160        this.items = [100, 200, 300];
161      })
162    }
163  }
164}
165
166@Entry
167@Component
168struct Parent {
169  @State arr: number[] = [1, 2, 3];
170
171  build() {
172    Column() {
173      Child({ items: $arr })
174      ForEach(this.arr,
175        item => {
176          Text(`${item}`)
177        },
178        item => item.toString()
179      )
180    }
181  }
182}
183```
184
185
186As described above, the ArkUI framework can observe the addition, deletion, and replacement of array items. It should be noted that, in the preceding example, the type of the \@Link and \@State decorated variables is the same: number[]. It is not allowed to define the \@Link decorated variable in the child component as type number (**\@Link item: number**), and create child components for each array item in the \@State decorated array in the parent component. [\@Prop](arkts-prop.md) or \@Observed should be used depending on application semantics.
187