ts-component-states-link.md 4.6 KB
Newer Older
Z
zengyawen 已提交
1 2
# @Link<a name="EN-US_TOPIC_0000001110948894"></a>

Z
zengyawen 已提交
3
Two-way binding can be established between the  **@Link**  decorated variable and the  **@State**  decorated variable of the parent component. The  **@Link**  data has the following features:
Z
zengyawen 已提交
4

Z
zengyawen 已提交
5
-   **Support for multiple types**: The value of the  **@Link**  decorated variable can be of the same type as the  **@State**  decorated variable; that is, the value can be of the following types:  **class**,  **number**,  **string**,  **boolean**, or arrays of these types.
Z
zengyawen 已提交
6
-   **Private**: Data is accessed only within the component.
Z
zengyawen 已提交
7 8 9
-   **Single data source**: The variable of the parent component for initializing the  **@Link**  decorated variable must be the  **@State**  decorated variable.
-   **Two-way binding**: When a child component changes the  **@Link**  decorated variable, the  **@State**  decorated variable of its parent component is also changed.
-   **Support for initialization with the variable reference passed to the @Link decorated variable**: When creating a new instance of the component, you must use the naming parameter to initialize all  **@Link**  decorated variables. The  **@Link**  decorated variable can be initialized by using the reference of the  **@State**  or  **@Link**  decorated variable. Wherein, the  **@State**  decorated variable can be referenced using the '**$**' operator.
Z
zengyawen 已提交
10

Z
zengyawen 已提交
11 12
>![](../public_sys-resources/icon-note.gif) **NOTE:** 
>The  **@Link**  decorated variable cannot be initialized within the component.
Z
zengyawen 已提交
13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43

## Simple Type Example<a name="section19793192619582"></a>

```
@Entry
@Component
struct Player {
    @State isPlaying: boolean = false
    build() {
        Column() {
            PlayButton({buttonPlaying: $isPlaying})
            Text(`Player is ${this.isPlaying? '':'not'} playing`)
        }
    }
}

@Component
struct PlayButton {
    @Link buttonPlaying: boolean
    build() {
        Column() {
            Button() {
                Image(this.buttonPlaying? 'play.png' : 'pause.png')
            }.onClick(() => {
                this.buttonPlaying = !this.buttonPlaying
            })
        }
    }
}
```

Z
zengyawen 已提交
44
The  **@Link**  semantics are derived from the '**$**' operator. In other words,  **$isPlaying**  is the two-way binding of the internal state  **this.isPlaying**. When you click  **PlayButton**, the  **<Image\>**  and  **<Text\>**  components of  **PlayButton**  are refreshed at the same time.
Z
zengyawen 已提交
45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82

## Complex Type Example<a name="section2921131712010"></a>

```
@Entry
@Component
struct Parent {
    @State arr: number[] = [1, 2, 3]
    build() {
        Column() {
            Child({items: $arr})
            ForEach(this.arr,
                item => Text(`${item}`),
                item => item.toString())
        }
    }
}

@Component
struct Child {
    @Link items: number[]
    build() {
        Column() {
            Button() {
                Text('Button1: push')
            }.onClick(() => {
                this.items.push(100)
            })
            Button() {
                Text('Button2: replace whole item')
            }.onClick(() => {
                this.items = [100, 200, 300]
            })
        }
    }
}
```

Z
zengyawen 已提交
83
In the example above, click  **Button1**  and  **Button2**  to change the list of text items displayed in the parent component.
Z
zengyawen 已提交
84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120

## Example of Using @Link, @State, and @Prop Together<a name="section17490315415"></a>

```
@Entry
@Component
struct ParentView {
    @State counter: number = 0
    build() {
        Column() {
            ChildA({counterVal: this.counter})  // pass by value
            ChildB({counterRef: $counter})      // $ creates a Reference that can be bound to counterRef
        }
    }
}

@Component
struct ChildA {
    @Prop counterVal: number
    build() {
        Button() {
            Text(`ChildA: (${this.counterVal}) + 1`)
        }.onClick(() => {this.counterVal+= 1})
    }
}

@Component
struct ChildB {
    @Link counterRef: number
    build() {
        Button() {
            Text(`ChildB: (${this.counterRef}) + 1`)
        }.onClick(() => {this.counterRef+= 1})
    }
}
```

Z
zengyawen 已提交
121
In the preceding example,  **ParentView**  contains two child components:  **ChildA**  and  **ChildB**. They are initialized by the state variable  **counter**  of  **ParentView**.
Z
zengyawen 已提交
122

Z
zengyawen 已提交
123 124
-   **ChildB**  uses  **@Link**  to establish two-way state binding. When the value of the  **counterRef**  state variable is changed in  **ChildB**, the change is synchronized to  **ParentView**  and  **ChildA**.
-   **ChildA**  uses  **@Prop**  to establish one-way state binding from  **ParentView**  to itself. When  **ChildA**  changes the state, it is re-rendered, but the change is not updated to  **ParentView**  or  **ChildB**.
Z
zengyawen 已提交
125