1e41f4b71Sopenharmony_ci# \@Param:组件外部输入
2e41f4b71Sopenharmony_ci
3e41f4b71Sopenharmony_ci
4e41f4b71Sopenharmony_ci为了增强子组件接受外部参数输入的能力,开发者可以使用\@Param装饰器。
5e41f4b71Sopenharmony_ci
6e41f4b71Sopenharmony_ci> **说明:**
7e41f4b71Sopenharmony_ci>
8e41f4b71Sopenharmony_ci> 从API version 12开始,在\@ComponentV2装饰的自定义组件中支持使用\@Param装饰器。
9e41f4b71Sopenharmony_ci>
10e41f4b71Sopenharmony_ci>当前状态管理(V2试用版)仍在逐步开发中,相关功能尚未成熟,建议开发者尝鲜试用。
11e41f4b71Sopenharmony_ci
12e41f4b71Sopenharmony_ci
13e41f4b71Sopenharmony_ci
14e41f4b71Sopenharmony_ci## 概述
15e41f4b71Sopenharmony_ci
16e41f4b71Sopenharmony_ci\@Param表示组件从外部传入的状态,使得父子组件之间的数据能够进行同步:
17e41f4b71Sopenharmony_ci
18e41f4b71Sopenharmony_ci- \@Param装饰的变量支持本地初始化,但是不允许在组件内部直接修改变量本身。
19e41f4b71Sopenharmony_ci
20e41f4b71Sopenharmony_ci- 被\@Param装饰的变量能够在初始化自定义组件时从外部传入,当数据源也是状态变量时,数据源的修改会同步给\@Param。
21e41f4b71Sopenharmony_ci- \@Param可以接受任意类型的数据源,包括普通变量、状态变量、常量、函数返回值等。
22e41f4b71Sopenharmony_ci- \@Param装饰的变量变化时,会刷新该变量关联的组件。
23e41f4b71Sopenharmony_ci- \@Param支持观测number、boolean、string、Object、class等基本类型以及Array、Set、Map、Date等内嵌类型。
24e41f4b71Sopenharmony_ci- 对于复杂类型如类对象,\@Param会接受数据源的引用。在组件内可以修改类对象中的属性,该修改会同步到数据源。
25e41f4b71Sopenharmony_ci- \@Param的观测能力仅限于被装饰的变量本身。当装饰简单类型时,对变量的整体改变能够观测到;当装饰对象类型时,仅能观测对象整体的改变;当装饰数组类型时,能观测到数组整体以及数组元素项的改变;当装饰Array、Set、Map、Date等内嵌类型时,可以观测到通过API调用带来的变化。详见[观察变化](#观察变化)。
26e41f4b71Sopenharmony_ci- \@Param支持null、undefined以及联合类型。
27e41f4b71Sopenharmony_ci
28e41f4b71Sopenharmony_ci
29e41f4b71Sopenharmony_ci## 状态管理V1版本接受外部传入的装饰器的局限性
30e41f4b71Sopenharmony_ci状态管理V1存在多种可接受外部传入的装饰器,常用的有\@State、\@Prop、\@Link、\@ObjectLink。这些装饰器使用各有限制,不易区分,当使用不当时,还会导致性能问题。
31e41f4b71Sopenharmony_ci
32e41f4b71Sopenharmony_ci```ts
33e41f4b71Sopenharmony_ci@Observed
34e41f4b71Sopenharmony_ciclass Region {
35e41f4b71Sopenharmony_ci  x: number;
36e41f4b71Sopenharmony_ci  y: number;
37e41f4b71Sopenharmony_ci  constructor(x: number, y: number) {
38e41f4b71Sopenharmony_ci    this.x = x;
39e41f4b71Sopenharmony_ci    this.y = y;
40e41f4b71Sopenharmony_ci  }
41e41f4b71Sopenharmony_ci}
42e41f4b71Sopenharmony_ci@Observed
43e41f4b71Sopenharmony_ciclass Info {
44e41f4b71Sopenharmony_ci  region: Region;
45e41f4b71Sopenharmony_ci  constructor(x: number, y: number) {
46e41f4b71Sopenharmony_ci    this.region = new Region(x, y);
47e41f4b71Sopenharmony_ci  }
48e41f4b71Sopenharmony_ci}
49e41f4b71Sopenharmony_ci@Entry
50e41f4b71Sopenharmony_ci@Component
51e41f4b71Sopenharmony_cistruct Index {
52e41f4b71Sopenharmony_ci  @State info: Info = new Info(0, 0);
53e41f4b71Sopenharmony_ci  
54e41f4b71Sopenharmony_ci  build() {
55e41f4b71Sopenharmony_ci    Column() {
56e41f4b71Sopenharmony_ci      Button("change Info")
57e41f4b71Sopenharmony_ci        .onClick(() => {
58e41f4b71Sopenharmony_ci          this.info = new Info(100, 100);
59e41f4b71Sopenharmony_ci      })
60e41f4b71Sopenharmony_ci      Child({
61e41f4b71Sopenharmony_ci        region: this.info.region,
62e41f4b71Sopenharmony_ci        regionProp: this.info.region,
63e41f4b71Sopenharmony_ci        infoProp: this.info,
64e41f4b71Sopenharmony_ci        infoLink: this.info,
65e41f4b71Sopenharmony_ci        infoState: this.info
66e41f4b71Sopenharmony_ci      })
67e41f4b71Sopenharmony_ci    }
68e41f4b71Sopenharmony_ci  }
69e41f4b71Sopenharmony_ci}
70e41f4b71Sopenharmony_ci@Component
71e41f4b71Sopenharmony_cistruct Child {
72e41f4b71Sopenharmony_ci  @ObjectLink region: Region;
73e41f4b71Sopenharmony_ci  @Prop regionProp: Region;
74e41f4b71Sopenharmony_ci  @Prop infoProp: Info;
75e41f4b71Sopenharmony_ci  @Link infoLink: Info;
76e41f4b71Sopenharmony_ci  @State infoState: Info = new Info(1, 1);
77e41f4b71Sopenharmony_ci  build() {
78e41f4b71Sopenharmony_ci    Column() {
79e41f4b71Sopenharmony_ci      Text(`ObjectLink region: ${this.region.x}-${this.region.y}`)
80e41f4b71Sopenharmony_ci      Text(`Prop regionProp: ${this.regionProp.x}-${this.regionProp.y}`)
81e41f4b71Sopenharmony_ci    }
82e41f4b71Sopenharmony_ci  }
83e41f4b71Sopenharmony_ci}
84e41f4b71Sopenharmony_ci```
85e41f4b71Sopenharmony_ci
86e41f4b71Sopenharmony_ci在上面的示例中,\@State仅能在初始化时获得info的引用,当改变info之后,无法进行同步。\@Prop虽然能够进行单向同步,但是对于较复杂的类型来说,深拷贝性能较差。\@Link能够接受传入的引用进行双向同步,但它必须要求数据源也是状态变量,因此无法接受info中的成员属性region。\@ObjectLink能够接受类成员属性,但是要求该属性类型必须为\@Observed装饰的类。装饰器的不同限制使得父子组件之间传值规则十分复杂,不易使用。因此推出\@Param装饰器表示组件从外部传入的状态。
87e41f4b71Sopenharmony_ci
88e41f4b71Sopenharmony_ci## 装饰器说明
89e41f4b71Sopenharmony_ci
90e41f4b71Sopenharmony_ci| \@Param变量装饰器  | 说明                                                         |
91e41f4b71Sopenharmony_ci| ------------------ | ------------------------------------------------------------ |
92e41f4b71Sopenharmony_ci| 装饰器参数         | 无。                                                         |
93e41f4b71Sopenharmony_ci| 能否本地修改       | 否,修改值需使用\@Event装饰器的能力。                        |
94e41f4b71Sopenharmony_ci| 同步类型           | 由父到子单向同步。                                           |
95e41f4b71Sopenharmony_ci| 允许装饰的变量类型 | Object、class、string、number、boolean、enum等基本类型以及Array、Date、Map、Set等内嵌类型。支持null、undefined以及联合类型。 |
96e41f4b71Sopenharmony_ci| 被装饰变量的初始值 | 允许本地初始化,若不在本地初始化,则需要和\@Require装饰器一起使用,要求必须从外部传入初始化。 |
97e41f4b71Sopenharmony_ci
98e41f4b71Sopenharmony_ci## 变量传递
99e41f4b71Sopenharmony_ci
100e41f4b71Sopenharmony_ci| 传递规则       | 说明                                                         |
101e41f4b71Sopenharmony_ci| -------------- | ------------------------------------------------------------ |
102e41f4b71Sopenharmony_ci| 从父组件初始化 | \@Param装饰的变量允许本地初始化,若无本地初始化则必须从外部传入初始化。当同时存在本地初始值与外部传入值时,会优先使用外部传入值进行初始化 |
103e41f4b71Sopenharmony_ci| 初始化子组件   | \@Param装饰的变量可以初始化子组件中\@Param装饰的变量。       |
104e41f4b71Sopenharmony_ci| 同步           | \@Param可以和父组件传入的状态变量数据源(即\@Local或\@Param装饰的变量)进行同步,当数据源发生变化时,会将修改同步给子组件的\@Param。 |
105e41f4b71Sopenharmony_ci
106e41f4b71Sopenharmony_ci## 观察变化
107e41f4b71Sopenharmony_ci
108e41f4b71Sopenharmony_ci使用\@Param装饰的变量具有被观测变化的能力。当装饰的变量发生变化时,会触发该变量绑定的UI组件刷新。
109e41f4b71Sopenharmony_ci
110e41f4b71Sopenharmony_ci- 当装饰的变量类型为boolean、string、number类型时,可以观察来自数据源同步的变化。
111e41f4b71Sopenharmony_ci
112e41f4b71Sopenharmony_ci  ```ts
113e41f4b71Sopenharmony_ci  @Entry
114e41f4b71Sopenharmony_ci  @ComponentV2
115e41f4b71Sopenharmony_ci  struct Index {
116e41f4b71Sopenharmony_ci    @Local count: number = 0;
117e41f4b71Sopenharmony_ci    @Local message: string = "Hello";
118e41f4b71Sopenharmony_ci    @Local flag: boolean = false;
119e41f4b71Sopenharmony_ci    build() {
120e41f4b71Sopenharmony_ci      Column() {
121e41f4b71Sopenharmony_ci        Text(`Local ${this.count}`)
122e41f4b71Sopenharmony_ci        Text(`Local ${this.message}`)
123e41f4b71Sopenharmony_ci        Text(`Local ${this.flag}`)
124e41f4b71Sopenharmony_ci        Button("change Local")
125e41f4b71Sopenharmony_ci          .onClick(()=>{
126e41f4b71Sopenharmony_ci            // 对数据源的更改会同步给子组件
127e41f4b71Sopenharmony_ci            this.count++;
128e41f4b71Sopenharmony_ci            this.message += " World";
129e41f4b71Sopenharmony_ci            this.flag = !this.flag;
130e41f4b71Sopenharmony_ci        })
131e41f4b71Sopenharmony_ci        Child({
132e41f4b71Sopenharmony_ci          count: this.count,
133e41f4b71Sopenharmony_ci          message: this.message,
134e41f4b71Sopenharmony_ci          flag: this.flag
135e41f4b71Sopenharmony_ci        })
136e41f4b71Sopenharmony_ci      }
137e41f4b71Sopenharmony_ci    }
138e41f4b71Sopenharmony_ci  }
139e41f4b71Sopenharmony_ci  @ComponentV2
140e41f4b71Sopenharmony_ci  struct Child {
141e41f4b71Sopenharmony_ci    @Require @Param count: number;
142e41f4b71Sopenharmony_ci    @Require @Param message: string;
143e41f4b71Sopenharmony_ci    @Require @Param flag: boolean;
144e41f4b71Sopenharmony_ci    build() {
145e41f4b71Sopenharmony_ci      Column() {
146e41f4b71Sopenharmony_ci        Text(`Param ${this.count}`)
147e41f4b71Sopenharmony_ci        Text(`Param ${this.message}`)
148e41f4b71Sopenharmony_ci        Text(`Param ${this.flag}`)
149e41f4b71Sopenharmony_ci      }
150e41f4b71Sopenharmony_ci    }
151e41f4b71Sopenharmony_ci  }
152e41f4b71Sopenharmony_ci  ```
153e41f4b71Sopenharmony_ci
154e41f4b71Sopenharmony_ci- 当装饰的变量类型为类对象时,仅可以观察到对类对象整体赋值的变化,无法直接观察到对类成员属性赋值的变化,对类成员属性的观察依赖\@ObservedV2和\@Trace装饰器。
155e41f4b71Sopenharmony_ci
156e41f4b71Sopenharmony_ci  ```ts
157e41f4b71Sopenharmony_ci  class RawObject {
158e41f4b71Sopenharmony_ci    name: string;
159e41f4b71Sopenharmony_ci    constructor(name: string) {
160e41f4b71Sopenharmony_ci      this.name = name;
161e41f4b71Sopenharmony_ci    }
162e41f4b71Sopenharmony_ci  }
163e41f4b71Sopenharmony_ci  @ObservedV2
164e41f4b71Sopenharmony_ci  class ObservedObject {
165e41f4b71Sopenharmony_ci    @Trace name: string;
166e41f4b71Sopenharmony_ci    constructor(name: string) {
167e41f4b71Sopenharmony_ci      this.name = name;
168e41f4b71Sopenharmony_ci    }
169e41f4b71Sopenharmony_ci  }
170e41f4b71Sopenharmony_ci  @Entry
171e41f4b71Sopenharmony_ci  @ComponentV2
172e41f4b71Sopenharmony_ci  struct Index {
173e41f4b71Sopenharmony_ci    @Local rawObject: RawObject = new RawObject("rawObject");
174e41f4b71Sopenharmony_ci    @Local observedObject: ObservedObject = new ObservedObject("observedObject");
175e41f4b71Sopenharmony_ci    build() {
176e41f4b71Sopenharmony_ci      Column() {
177e41f4b71Sopenharmony_ci        Text(`${this.rawObject.name}`)
178e41f4b71Sopenharmony_ci        Text(`${this.observedObject.name}`)
179e41f4b71Sopenharmony_ci        Button("change object")
180e41f4b71Sopenharmony_ci          .onClick(() => {
181e41f4b71Sopenharmony_ci            // 对类对象整体的修改均能观察到
182e41f4b71Sopenharmony_ci            this.rawObject = new RawObject("new rawObject");
183e41f4b71Sopenharmony_ci            this.observedObject = new ObservedObject("new observedObject");
184e41f4b71Sopenharmony_ci        })
185e41f4b71Sopenharmony_ci        Button("change name")
186e41f4b71Sopenharmony_ci          .onClick(() => {
187e41f4b71Sopenharmony_ci            // \@Local与\@Param均不具备观察类对象属性的能力,因此对rawObject.name的修改无法观察到
188e41f4b71Sopenharmony_ci            this.rawObject.name = "new rawObject name";
189e41f4b71Sopenharmony_ci            // 由于ObservedObject的name属性被@Trace装饰,因此对observedObject.name的修改能被观察到
190e41f4b71Sopenharmony_ci            this.observedObject.name = "new observedObject name";
191e41f4b71Sopenharmony_ci        })
192e41f4b71Sopenharmony_ci        Child({
193e41f4b71Sopenharmony_ci          rawObject: this.rawObject,
194e41f4b71Sopenharmony_ci          observedObject: this.observedObject
195e41f4b71Sopenharmony_ci        })
196e41f4b71Sopenharmony_ci      }
197e41f4b71Sopenharmony_ci    }
198e41f4b71Sopenharmony_ci  }
199e41f4b71Sopenharmony_ci  @ComponentV2
200e41f4b71Sopenharmony_ci  struct Child {
201e41f4b71Sopenharmony_ci    @Require @Param rawObject: RawObject;
202e41f4b71Sopenharmony_ci    @Require @Param observedObject: ObservedObject;
203e41f4b71Sopenharmony_ci    build() {
204e41f4b71Sopenharmony_ci      Column() {
205e41f4b71Sopenharmony_ci        Text(`${this.rawObject.name}`)
206e41f4b71Sopenharmony_ci        Text(`${this.observedObject.name}`)
207e41f4b71Sopenharmony_ci      }
208e41f4b71Sopenharmony_ci    }
209e41f4b71Sopenharmony_ci    
210e41f4b71Sopenharmony_ci  }
211e41f4b71Sopenharmony_ci  ```
212e41f4b71Sopenharmony_ci
213e41f4b71Sopenharmony_ci- 当装饰的变量类型为简单类型的数组时,可以观察到数组整体或数组项的变化。
214e41f4b71Sopenharmony_ci
215e41f4b71Sopenharmony_ci  ```ts
216e41f4b71Sopenharmony_ci  @Entry
217e41f4b71Sopenharmony_ci  @ComponentV2
218e41f4b71Sopenharmony_ci  struct Index {
219e41f4b71Sopenharmony_ci    @Local numArr: number[] = [1,2,3,4,5];
220e41f4b71Sopenharmony_ci    @Local dimensionTwo: number[][] = [[1,2,3],[4,5,6]];
221e41f4b71Sopenharmony_ci    
222e41f4b71Sopenharmony_ci    build() {
223e41f4b71Sopenharmony_ci      Column() {
224e41f4b71Sopenharmony_ci        Text(`${this.numArr[0]}`)
225e41f4b71Sopenharmony_ci        Text(`${this.numArr[1]}`)
226e41f4b71Sopenharmony_ci        Text(`${this.numArr[2]}`)
227e41f4b71Sopenharmony_ci        Text(`${this.dimensionTwo[0][0]}`)
228e41f4b71Sopenharmony_ci        Text(`${this.dimensionTwo[1][1]}`)
229e41f4b71Sopenharmony_ci        Button("change array item")
230e41f4b71Sopenharmony_ci          .onClick(() => {
231e41f4b71Sopenharmony_ci            this.numArr[0]++;
232e41f4b71Sopenharmony_ci            this.numArr[1] += 2;
233e41f4b71Sopenharmony_ci            this.dimensionTwo[0][0] = 0;
234e41f4b71Sopenharmony_ci            this.dimensionTwo[1][1] = 0;
235e41f4b71Sopenharmony_ci          })
236e41f4b71Sopenharmony_ci        Button("change whole array")
237e41f4b71Sopenharmony_ci          .onClick(() => {
238e41f4b71Sopenharmony_ci            this.numArr = [5,4,3,2,1];
239e41f4b71Sopenharmony_ci            this.dimensionTwo = [[7,8,9],[0,1,2]];
240e41f4b71Sopenharmony_ci          })
241e41f4b71Sopenharmony_ci        Child({
242e41f4b71Sopenharmony_ci          numArr: this.numArr,
243e41f4b71Sopenharmony_ci          dimensionTwo: this.dimensionTwo
244e41f4b71Sopenharmony_ci        })
245e41f4b71Sopenharmony_ci      }
246e41f4b71Sopenharmony_ci    }
247e41f4b71Sopenharmony_ci  }
248e41f4b71Sopenharmony_ci  @ComponentV2
249e41f4b71Sopenharmony_ci  struct Child {
250e41f4b71Sopenharmony_ci    @Require @Param numArr: number[];
251e41f4b71Sopenharmony_ci    @Require @Param dimensionTwo: number[][];
252e41f4b71Sopenharmony_ci    
253e41f4b71Sopenharmony_ci    build() {
254e41f4b71Sopenharmony_ci      Column() {
255e41f4b71Sopenharmony_ci        Text(`${this.numArr[0]}`)
256e41f4b71Sopenharmony_ci        Text(`${this.numArr[1]}`)
257e41f4b71Sopenharmony_ci        Text(`${this.numArr[2]}`)
258e41f4b71Sopenharmony_ci        Text(`${this.dimensionTwo[0][0]}`)
259e41f4b71Sopenharmony_ci        Text(`${this.dimensionTwo[1][1]}`)
260e41f4b71Sopenharmony_ci      }
261e41f4b71Sopenharmony_ci    }
262e41f4b71Sopenharmony_ci  }
263e41f4b71Sopenharmony_ci  ```
264e41f4b71Sopenharmony_ci
265e41f4b71Sopenharmony_ci- 当装饰的变量是嵌套类或对象数组时,\@Param无法观察深层对象属性的变化。对深层对象属性的观测依赖\@ObservedV2与\@Trace装饰器。
266e41f4b71Sopenharmony_ci
267e41f4b71Sopenharmony_ci  ```ts
268e41f4b71Sopenharmony_ci  @ObservedV2
269e41f4b71Sopenharmony_ci  class Region {
270e41f4b71Sopenharmony_ci    @Trace x: number;
271e41f4b71Sopenharmony_ci    @Trace y: number;
272e41f4b71Sopenharmony_ci    constructor(x: number, y: number) {
273e41f4b71Sopenharmony_ci      this.x = x;
274e41f4b71Sopenharmony_ci      this.y = y;
275e41f4b71Sopenharmony_ci    }
276e41f4b71Sopenharmony_ci  }
277e41f4b71Sopenharmony_ci  @ObservedV2
278e41f4b71Sopenharmony_ci  class Info {
279e41f4b71Sopenharmony_ci    @Trace region: Region;
280e41f4b71Sopenharmony_ci    @Trace name: string;
281e41f4b71Sopenharmony_ci    constructor(name: string, x: number, y: number) {
282e41f4b71Sopenharmony_ci      this.name = name;
283e41f4b71Sopenharmony_ci      this.region = new Region(x, y);
284e41f4b71Sopenharmony_ci    }
285e41f4b71Sopenharmony_ci  }
286e41f4b71Sopenharmony_ci  @Entry
287e41f4b71Sopenharmony_ci  @ComponentV2
288e41f4b71Sopenharmony_ci  struct Index {
289e41f4b71Sopenharmony_ci    @Local infoArr: Info[] = [new Info("Ocean", 28, 120), new Info("Mountain", 26, 20)];
290e41f4b71Sopenharmony_ci    @Local originInfo: Info = new Info("Origin", 0, 0);
291e41f4b71Sopenharmony_ci    build() {
292e41f4b71Sopenharmony_ci      Column() {
293e41f4b71Sopenharmony_ci        ForEach(this.infoArr, (info: Info) => {
294e41f4b71Sopenharmony_ci          Row() {
295e41f4b71Sopenharmony_ci            Text(`name: ${info.name}`)
296e41f4b71Sopenharmony_ci            Text(`region: ${info.region.x}-${info.region.y}`)
297e41f4b71Sopenharmony_ci          }
298e41f4b71Sopenharmony_ci        })
299e41f4b71Sopenharmony_ci        Row() {
300e41f4b71Sopenharmony_ci          Text(`Origin name: ${this.originInfo.name}`)
301e41f4b71Sopenharmony_ci          Text(`Origin region: ${this.originInfo.region.x}-${this.originInfo.region.y}`)
302e41f4b71Sopenharmony_ci        }
303e41f4b71Sopenharmony_ci        Button("change infoArr item")
304e41f4b71Sopenharmony_ci          .onClick(() => {
305e41f4b71Sopenharmony_ci            // 由于属性name被@Trace装饰,所以能够观察到
306e41f4b71Sopenharmony_ci            this.infoArr[0].name = "Win";
307e41f4b71Sopenharmony_ci          })
308e41f4b71Sopenharmony_ci        Button("change originInfo")
309e41f4b71Sopenharmony_ci          .onClick(() => {
310e41f4b71Sopenharmony_ci            // 由于变量originInfo被@Local装饰,所以能够观察到
311e41f4b71Sopenharmony_ci            this.originInfo = new Info("Origin", 100, 100);
312e41f4b71Sopenharmony_ci          })
313e41f4b71Sopenharmony_ci        Button("change originInfo region")
314e41f4b71Sopenharmony_ci          .onClick(() => {
315e41f4b71Sopenharmony_ci            // 由于属性x、y被@Trace装饰,所以能够观察到
316e41f4b71Sopenharmony_ci            this.originInfo.region.x = 25;
317e41f4b71Sopenharmony_ci            this.originInfo.region.y = 25;
318e41f4b71Sopenharmony_ci          })
319e41f4b71Sopenharmony_ci      }
320e41f4b71Sopenharmony_ci    }
321e41f4b71Sopenharmony_ci  }
322e41f4b71Sopenharmony_ci  @ComponentV2
323e41f4b71Sopenharmony_ci  struct Child {
324e41f4b71Sopenharmony_ci    @Param infoArr: Info[] = [];
325e41f4b71Sopenharmony_ci    @Param originInfo: Info = new Info("O", 0, 0);
326e41f4b71Sopenharmony_ci  
327e41f4b71Sopenharmony_ci    build() {
328e41f4b71Sopenharmony_ci      Column() {
329e41f4b71Sopenharmony_ci        ForEach(this.infoArr, (info: Info) => {
330e41f4b71Sopenharmony_ci          Row() {
331e41f4b71Sopenharmony_ci            Text(`name: ${info.name}`)
332e41f4b71Sopenharmony_ci            Text(`region: ${info.region.x}-${info.region.y}`)
333e41f4b71Sopenharmony_ci          }
334e41f4b71Sopenharmony_ci        })
335e41f4b71Sopenharmony_ci        Row() {
336e41f4b71Sopenharmony_ci          Text(`Origin name: ${this.originInfo.name}`)
337e41f4b71Sopenharmony_ci          Text(`Origin region: ${this.originInfo.region.x}-${this.originInfo.region.y}`)
338e41f4b71Sopenharmony_ci        }
339e41f4b71Sopenharmony_ci      }
340e41f4b71Sopenharmony_ci    }
341e41f4b71Sopenharmony_ci  }
342e41f4b71Sopenharmony_ci  ```
343e41f4b71Sopenharmony_ci
344e41f4b71Sopenharmony_ci- 当装饰的变量类型是内置类型时,可以观察到变量整体赋值以及通过API调用带来的变化。
345e41f4b71Sopenharmony_ci
346e41f4b71Sopenharmony_ci  | 类型  | 可观测变化的API                                              |
347e41f4b71Sopenharmony_ci  | ----- | ------------------------------------------------------------ |
348e41f4b71Sopenharmony_ci  | Array | push、pop、shift、unshift、splice、copyWithin、fill、reverse、sort |
349e41f4b71Sopenharmony_ci  | Date  | setFullYear, setMonth, setDate, setHours, setMinutes, setSeconds, setMilliseconds, setTime, setUTCFullYear, setUTCMonth, setUTCDate, setUTCHours, setUTCMinutes, setUTCSeconds, setUTCMilliseconds |
350e41f4b71Sopenharmony_ci  | Map   | set, clear, delete                                           |
351e41f4b71Sopenharmony_ci  | Set   | add, clear, delete                                           |
352e41f4b71Sopenharmony_ci
353e41f4b71Sopenharmony_ci## 限制条件
354e41f4b71Sopenharmony_ci
355e41f4b71Sopenharmony_ci\@Param装饰器存在以下使用限制:
356e41f4b71Sopenharmony_ci
357e41f4b71Sopenharmony_ci- \@Param装饰器只能在\@ComponentV2装饰器的自定义组件中使用。
358e41f4b71Sopenharmony_ci
359e41f4b71Sopenharmony_ci  ```ts
360e41f4b71Sopenharmony_ci  @ComponentV2
361e41f4b71Sopenharmony_ci  struct CompA {
362e41f4b71Sopenharmony_ci    @Param message: string = "Hello World"; // 正确用法
363e41f4b71Sopenharmony_ci    build() {
364e41f4b71Sopenharmony_ci    }
365e41f4b71Sopenharmony_ci  }
366e41f4b71Sopenharmony_ci  @Component
367e41f4b71Sopenharmony_ci  struct CompB {
368e41f4b71Sopenharmony_ci    @Param message: string = "Hello World"; // 错误用法
369e41f4b71Sopenharmony_ci    build() {
370e41f4b71Sopenharmony_ci    }
371e41f4b71Sopenharmony_ci  }
372e41f4b71Sopenharmony_ci  ```
373e41f4b71Sopenharmony_ci
374e41f4b71Sopenharmony_ci- \@Param装饰的变量表示组件外部输入,需要被初始化。支持使用本地初始值做初始化。当存在外部传入值时,将优先使用外部传入的值初始化。既不使用本地初始值,也不使用外部传入值是不允许的。
375e41f4b71Sopenharmony_ci
376e41f4b71Sopenharmony_ci  ```ts
377e41f4b71Sopenharmony_ci  @ComponentV2
378e41f4b71Sopenharmony_ci  struct CompA {
379e41f4b71Sopenharmony_ci    @Param param1: string = "Initialize local";
380e41f4b71Sopenharmony_ci    @Param param2: string = "Initialize local and put in";
381e41f4b71Sopenharmony_ci    @Require @Param param3: string;
382e41f4b71Sopenharmony_ci    build() {
383e41f4b71Sopenharmony_ci      Column() {
384e41f4b71Sopenharmony_ci        Text(`${this.param1}`) // Initialize local
385e41f4b71Sopenharmony_ci        Text(`${this.param2}`) // Put in
386e41f4b71Sopenharmony_ci        Text(`${this.param3}`) // Put in
387e41f4b71Sopenharmony_ci      }
388e41f4b71Sopenharmony_ci    }
389e41f4b71Sopenharmony_ci  }
390e41f4b71Sopenharmony_ci  @Entry
391e41f4b71Sopenharmony_ci  @ComponentV2
392e41f4b71Sopenharmony_ci  struct CompB {
393e41f4b71Sopenharmony_ci    @Local message: string = "Put in";
394e41f4b71Sopenharmony_ci    build() {
395e41f4b71Sopenharmony_ci      Column() {
396e41f4b71Sopenharmony_ci        CompA({
397e41f4b71Sopenharmony_ci          param2: this.message,
398e41f4b71Sopenharmony_ci          param3: this.message
399e41f4b71Sopenharmony_ci        })
400e41f4b71Sopenharmony_ci      }
401e41f4b71Sopenharmony_ci    }
402e41f4b71Sopenharmony_ci  }
403e41f4b71Sopenharmony_ci  ```
404e41f4b71Sopenharmony_ci
405e41f4b71Sopenharmony_ci- \@Param装饰的变量在子组件中无法进行修改。但当装饰的变量类型为对象时,在子组件中修改对象中属性是允许的。
406e41f4b71Sopenharmony_ci
407e41f4b71Sopenharmony_ci  ```ts
408e41f4b71Sopenharmony_ci  @ObservedV2
409e41f4b71Sopenharmony_ci  class Info {
410e41f4b71Sopenharmony_ci    @Trace name: string;
411e41f4b71Sopenharmony_ci    constructor(name: string) {
412e41f4b71Sopenharmony_ci      this.name = name;
413e41f4b71Sopenharmony_ci    }
414e41f4b71Sopenharmony_ci  }
415e41f4b71Sopenharmony_ci  @Entry
416e41f4b71Sopenharmony_ci  @ComponentV2
417e41f4b71Sopenharmony_ci  struct Index {
418e41f4b71Sopenharmony_ci    @Local info: Info = new Info("Tom");
419e41f4b71Sopenharmony_ci    build() {
420e41f4b71Sopenharmony_ci      Column() {
421e41f4b71Sopenharmony_ci        Text(`Parent info.name ${this.info.name}`)
422e41f4b71Sopenharmony_ci        Button("Parent change info")
423e41f4b71Sopenharmony_ci          .onClick(() => {
424e41f4b71Sopenharmony_ci            this.info = new Info("Lucy"); // 父组件更改@Local变量,会同步子组件对应@Param变量
425e41f4b71Sopenharmony_ci        })
426e41f4b71Sopenharmony_ci        Child({ info: this.info })
427e41f4b71Sopenharmony_ci      }
428e41f4b71Sopenharmony_ci    }
429e41f4b71Sopenharmony_ci  }
430e41f4b71Sopenharmony_ci  @ComponentV2
431e41f4b71Sopenharmony_ci  struct Child {
432e41f4b71Sopenharmony_ci    @Require @Param info: Info;
433e41f4b71Sopenharmony_ci    build() {
434e41f4b71Sopenharmony_ci      Column() {
435e41f4b71Sopenharmony_ci        Text(`info.name: ${this.info.name}`)
436e41f4b71Sopenharmony_ci        Button("change info")
437e41f4b71Sopenharmony_ci          .onClick(() => {
438e41f4b71Sopenharmony_ci            this.info = new Info("Jack"); //错误用法,不允许在子组件更改@Param变量
439e41f4b71Sopenharmony_ci          })
440e41f4b71Sopenharmony_ci        Button("Child change info.name")
441e41f4b71Sopenharmony_ci          .onClick(() => {
442e41f4b71Sopenharmony_ci            this.info.name = "Jack"; // 允许在子组件中更改对象中属性
443e41f4b71Sopenharmony_ci          })
444e41f4b71Sopenharmony_ci      }
445e41f4b71Sopenharmony_ci    }
446e41f4b71Sopenharmony_ci  }
447e41f4b71Sopenharmony_ci  ```
448e41f4b71Sopenharmony_ci
449e41f4b71Sopenharmony_ci## 使用场景
450e41f4b71Sopenharmony_ci
451e41f4b71Sopenharmony_ci### 从父组件到子组件变量传递与同步
452e41f4b71Sopenharmony_ci
453e41f4b71Sopenharmony_ci\@Param能够接受父组件\@Local或\@Param传递的数据并与之变化同步。
454e41f4b71Sopenharmony_ci
455e41f4b71Sopenharmony_ci```ts
456e41f4b71Sopenharmony_ci@ObservedV2
457e41f4b71Sopenharmony_ciclass Region {
458e41f4b71Sopenharmony_ci  @Trace x: number;
459e41f4b71Sopenharmony_ci  @Trace y: number;
460e41f4b71Sopenharmony_ci  constructor(x: number, y: number) {
461e41f4b71Sopenharmony_ci    this.x = x;
462e41f4b71Sopenharmony_ci    this.y = y;
463e41f4b71Sopenharmony_ci  }
464e41f4b71Sopenharmony_ci}
465e41f4b71Sopenharmony_ci@ObservedV2
466e41f4b71Sopenharmony_ciclass Info {
467e41f4b71Sopenharmony_ci  @Trace name: string;
468e41f4b71Sopenharmony_ci  @Trace age: number;
469e41f4b71Sopenharmony_ci  @Trace region: Region;
470e41f4b71Sopenharmony_ci  constructor(name: string, age: number, x: number, y: number) {
471e41f4b71Sopenharmony_ci    this.name = name;
472e41f4b71Sopenharmony_ci    this.age = age;
473e41f4b71Sopenharmony_ci    this.region = new Region(x, y);
474e41f4b71Sopenharmony_ci  }
475e41f4b71Sopenharmony_ci}
476e41f4b71Sopenharmony_ci@Entry
477e41f4b71Sopenharmony_ci@ComponentV2
478e41f4b71Sopenharmony_cistruct Index {
479e41f4b71Sopenharmony_ci  @Local infoList: Info[] = [new Info("Alice", 8, 0, 0), new Info("Barry", 10, 1, 20), new Info("Cindy", 18, 24, 40)];
480e41f4b71Sopenharmony_ci  build() {
481e41f4b71Sopenharmony_ci    Column() {
482e41f4b71Sopenharmony_ci      ForEach(this.infoList, (info: Info) => {
483e41f4b71Sopenharmony_ci        MiddleComponent({ info: info })
484e41f4b71Sopenharmony_ci      })
485e41f4b71Sopenharmony_ci      Button("change")
486e41f4b71Sopenharmony_ci        .onClick(() => {
487e41f4b71Sopenharmony_ci          this.infoList[0] = new Info("Atom", 40, 27, 90);
488e41f4b71Sopenharmony_ci          this.infoList[1].name = "Bob";
489e41f4b71Sopenharmony_ci          this.infoList[2].region = new Region(7, 9);
490e41f4b71Sopenharmony_ci        })
491e41f4b71Sopenharmony_ci    }
492e41f4b71Sopenharmony_ci  }
493e41f4b71Sopenharmony_ci}
494e41f4b71Sopenharmony_ci@ComponentV2
495e41f4b71Sopenharmony_cistruct MiddleComponent {
496e41f4b71Sopenharmony_ci  @Require @Param info: Info;
497e41f4b71Sopenharmony_ci  build() {
498e41f4b71Sopenharmony_ci    Column() {
499e41f4b71Sopenharmony_ci      Text(`name: ${this.info.name}`)
500e41f4b71Sopenharmony_ci      Text(`age: ${this.info.age}`)
501e41f4b71Sopenharmony_ci      SubComponent({ region: this.info.region })
502e41f4b71Sopenharmony_ci    }
503e41f4b71Sopenharmony_ci  }
504e41f4b71Sopenharmony_ci}
505e41f4b71Sopenharmony_ci@ComponentV2
506e41f4b71Sopenharmony_cistruct SubComponent {
507e41f4b71Sopenharmony_ci  @Require @Param region: Region;
508e41f4b71Sopenharmony_ci  build() {
509e41f4b71Sopenharmony_ci    Column() {
510e41f4b71Sopenharmony_ci      Text(`region: ${this.region.x}-${this.region.y}`)
511e41f4b71Sopenharmony_ci    }
512e41f4b71Sopenharmony_ci  }
513e41f4b71Sopenharmony_ci}
514e41f4b71Sopenharmony_ci```
515e41f4b71Sopenharmony_ci
516e41f4b71Sopenharmony_ci### 装饰Date类型变量
517e41f4b71Sopenharmony_ci
518e41f4b71Sopenharmony_ci\@Param装饰Date类型变量,可以观察到数据源对Date整体的赋值,以及调用Date的接口`setFullYear`, `setMonth`, `setDate`, `setHours`, `setMinutes`, `setSeconds`, `setMilliseconds`, `setTime`, `setUTCFullYear`, `setUTCMonth`, `setUTCDate`, `setUTCHours`, `setUTCMinutes`, `setUTCSeconds`, `setUTCMilliseconds` 带来的变化。
519e41f4b71Sopenharmony_ci
520e41f4b71Sopenharmony_ci```ts
521e41f4b71Sopenharmony_ci@ComponentV2
522e41f4b71Sopenharmony_cistruct DateComponent {
523e41f4b71Sopenharmony_ci  @Param selectedDate: Date = new Date('2024-01-01');
524e41f4b71Sopenharmony_ci
525e41f4b71Sopenharmony_ci  build() {
526e41f4b71Sopenharmony_ci    Column() {
527e41f4b71Sopenharmony_ci      DatePicker({
528e41f4b71Sopenharmony_ci        start: new Date('1970-1-1'),
529e41f4b71Sopenharmony_ci        end: new Date('2100-1-1'),
530e41f4b71Sopenharmony_ci        selected: this.selectedDate
531e41f4b71Sopenharmony_ci      })
532e41f4b71Sopenharmony_ci    }
533e41f4b71Sopenharmony_ci  }
534e41f4b71Sopenharmony_ci}
535e41f4b71Sopenharmony_ci
536e41f4b71Sopenharmony_ci@Entry
537e41f4b71Sopenharmony_ci@ComponentV2
538e41f4b71Sopenharmony_cistruct ParentComponent {
539e41f4b71Sopenharmony_ci  @Local parentSelectedDate: Date = new Date('2021-08-08');
540e41f4b71Sopenharmony_ci
541e41f4b71Sopenharmony_ci  build() {
542e41f4b71Sopenharmony_ci    Column() {
543e41f4b71Sopenharmony_ci      Button('parent update the new date')
544e41f4b71Sopenharmony_ci        .margin(10)
545e41f4b71Sopenharmony_ci        .onClick(() => {
546e41f4b71Sopenharmony_ci          this.parentSelectedDate = new Date('2023-07-07')
547e41f4b71Sopenharmony_ci        })
548e41f4b71Sopenharmony_ci      Button('increase the year by 1')
549e41f4b71Sopenharmony_ci        .margin(10)
550e41f4b71Sopenharmony_ci        .onClick(() => {
551e41f4b71Sopenharmony_ci        this.parentSelectedDate.setFullYear(this.parentSelectedDate.getFullYear() + 1)
552e41f4b71Sopenharmony_ci        })
553e41f4b71Sopenharmony_ci      Button('increase the month by 1')
554e41f4b71Sopenharmony_ci        .margin(10)
555e41f4b71Sopenharmony_ci        .onClick(() => {
556e41f4b71Sopenharmony_ci        this.parentSelectedDate.setMonth(this.parentSelectedDate.getMonth() + 1)
557e41f4b71Sopenharmony_ci        })
558e41f4b71Sopenharmony_ci      Button('parent increase the day by 1')
559e41f4b71Sopenharmony_ci        .margin(10)
560e41f4b71Sopenharmony_ci        .onClick(() => {
561e41f4b71Sopenharmony_ci   this.parentSelectedDate.setDate(this.parentSelectedDate.getDate() + 1)
562e41f4b71Sopenharmony_ci        })
563e41f4b71Sopenharmony_ci      DateComponent({ selectedDate: this.parentSelectedDate })
564e41f4b71Sopenharmony_ci    }
565e41f4b71Sopenharmony_ci  }
566e41f4b71Sopenharmony_ci}
567e41f4b71Sopenharmony_ci```
568e41f4b71Sopenharmony_ci
569e41f4b71Sopenharmony_ci### 装饰Map类型变量
570e41f4b71Sopenharmony_ci
571e41f4b71Sopenharmony_ci\@Param装饰Map类型变量,可以观察到数据源对Map整体的赋值,以及调用Map的接口 set、clear、delete带来的变化。
572e41f4b71Sopenharmony_ci
573e41f4b71Sopenharmony_ci```ts
574e41f4b71Sopenharmony_ci@ComponentV2
575e41f4b71Sopenharmony_cistruct Child {
576e41f4b71Sopenharmony_ci  @Param value: Map<number, string> = new Map()
577e41f4b71Sopenharmony_ci
578e41f4b71Sopenharmony_ci  build() {
579e41f4b71Sopenharmony_ci    Column() {
580e41f4b71Sopenharmony_ci      ForEach(Array.from(this.value.entries()), (item: [number, string]) => {
581e41f4b71Sopenharmony_ci        Text(`${item[0]}`).fontSize(30)
582e41f4b71Sopenharmony_ci        Text(`${item[1]}`).fontSize(30)
583e41f4b71Sopenharmony_ci        Divider()
584e41f4b71Sopenharmony_ci      })
585e41f4b71Sopenharmony_ci    }
586e41f4b71Sopenharmony_ci  }
587e41f4b71Sopenharmony_ci}
588e41f4b71Sopenharmony_ci@Entry
589e41f4b71Sopenharmony_ci@ComponentV2
590e41f4b71Sopenharmony_cistruct MapSample2 {
591e41f4b71Sopenharmony_ci  @Local message: Map<number, string> = new Map([[0, "a"], [1, "b"], [3, "c"]])
592e41f4b71Sopenharmony_ci
593e41f4b71Sopenharmony_ci  build() {
594e41f4b71Sopenharmony_ci    Row() {
595e41f4b71Sopenharmony_ci      Column() {
596e41f4b71Sopenharmony_ci        Child({ value: this.message })
597e41f4b71Sopenharmony_ci        Button('init map').onClick(() => {
598e41f4b71Sopenharmony_ci          this.message = new Map([[0, "a"], [1, "b"], [3, "c"]])
599e41f4b71Sopenharmony_ci        })
600e41f4b71Sopenharmony_ci        Button('set new one').onClick(() => {
601e41f4b71Sopenharmony_ci          this.message.set(4, "d")
602e41f4b71Sopenharmony_ci        })
603e41f4b71Sopenharmony_ci        Button('clear').onClick(() => {
604e41f4b71Sopenharmony_ci          this.message.clear()
605e41f4b71Sopenharmony_ci        })
606e41f4b71Sopenharmony_ci        Button('replace the first one').onClick(() => {
607e41f4b71Sopenharmony_ci          this.message.set(0, "aa")
608e41f4b71Sopenharmony_ci        })
609e41f4b71Sopenharmony_ci        Button('delete the first one').onClick(() => {
610e41f4b71Sopenharmony_ci          this.message.delete(0)
611e41f4b71Sopenharmony_ci        })
612e41f4b71Sopenharmony_ci      }
613e41f4b71Sopenharmony_ci      .width('100%')
614e41f4b71Sopenharmony_ci    }
615e41f4b71Sopenharmony_ci    .height('100%')
616e41f4b71Sopenharmony_ci  }
617e41f4b71Sopenharmony_ci}
618e41f4b71Sopenharmony_ci```
619e41f4b71Sopenharmony_ci
620e41f4b71Sopenharmony_ci### 装饰Set类型变量
621e41f4b71Sopenharmony_ci
622e41f4b71Sopenharmony_ci\@Param装饰Set类型变量,可以观察到数据源对Set整体的赋值,以及调用Set的接口 add、clear、delete带来的变化。
623e41f4b71Sopenharmony_ci
624e41f4b71Sopenharmony_ci```ts
625e41f4b71Sopenharmony_ci@ComponentV2
626e41f4b71Sopenharmony_cistruct Child {
627e41f4b71Sopenharmony_ci  @Param message: Set<number> = new Set()
628e41f4b71Sopenharmony_ci
629e41f4b71Sopenharmony_ci  build() {
630e41f4b71Sopenharmony_ci    Column() {
631e41f4b71Sopenharmony_ci      ForEach(Array.from(this.message.entries()), (item: [number, string]) => {
632e41f4b71Sopenharmony_ci        Text(`${item[0]}`).fontSize(30)
633e41f4b71Sopenharmony_ci        Divider()
634e41f4b71Sopenharmony_ci      })
635e41f4b71Sopenharmony_ci    }
636e41f4b71Sopenharmony_ci    .width('100%')
637e41f4b71Sopenharmony_ci  }
638e41f4b71Sopenharmony_ci}
639e41f4b71Sopenharmony_ci@Entry
640e41f4b71Sopenharmony_ci@ComponentV2
641e41f4b71Sopenharmony_cistruct SetSample11 {
642e41f4b71Sopenharmony_ci  @Local message: Set<number> = new Set([0, 1, 2, 3, 4])
643e41f4b71Sopenharmony_ci
644e41f4b71Sopenharmony_ci  build() {
645e41f4b71Sopenharmony_ci    Row() {
646e41f4b71Sopenharmony_ci      Column() {
647e41f4b71Sopenharmony_ci        Child({ message: this.message })
648e41f4b71Sopenharmony_ci        Button('init set').onClick(() => {
649e41f4b71Sopenharmony_ci          this.message = new Set([0, 1, 2, 3, 4])
650e41f4b71Sopenharmony_ci        })
651e41f4b71Sopenharmony_ci        Button('set new one').onClick(() => {
652e41f4b71Sopenharmony_ci          this.message.add(5)
653e41f4b71Sopenharmony_ci        })
654e41f4b71Sopenharmony_ci        Button('clear').onClick(() => {
655e41f4b71Sopenharmony_ci          this.message.clear()
656e41f4b71Sopenharmony_ci        })
657e41f4b71Sopenharmony_ci        Button('delete the first one').onClick(() => {
658e41f4b71Sopenharmony_ci          this.message.delete(0)
659e41f4b71Sopenharmony_ci        })
660e41f4b71Sopenharmony_ci      }
661e41f4b71Sopenharmony_ci      .width('100%')
662e41f4b71Sopenharmony_ci    }
663e41f4b71Sopenharmony_ci    .height('100%')
664e41f4b71Sopenharmony_ci  }
665e41f4b71Sopenharmony_ci}
666e41f4b71Sopenharmony_ci```
667e41f4b71Sopenharmony_ci
668e41f4b71Sopenharmony_ci### 联合类型
669e41f4b71Sopenharmony_ci
670e41f4b71Sopenharmony_ci\@Param支持null、undefined以及联合类型。在下面的示例中,count类型为number | undefined,点击改变count的类型,UI会随之刷新。
671e41f4b71Sopenharmony_ci
672e41f4b71Sopenharmony_ci```ts
673e41f4b71Sopenharmony_ci@Entry
674e41f4b71Sopenharmony_ci@ComponentV2
675e41f4b71Sopenharmony_cistruct Index {
676e41f4b71Sopenharmony_ci  @Local count: number | undefined = 0;
677e41f4b71Sopenharmony_ci
678e41f4b71Sopenharmony_ci  build() {
679e41f4b71Sopenharmony_ci    Column() {
680e41f4b71Sopenharmony_ci      MyComponent({ count: this.count })
681e41f4b71Sopenharmony_ci      Button('change')
682e41f4b71Sopenharmony_ci        .onClick(() => {
683e41f4b71Sopenharmony_ci          this.count = undefined;
684e41f4b71Sopenharmony_ci        })
685e41f4b71Sopenharmony_ci    }
686e41f4b71Sopenharmony_ci  }
687e41f4b71Sopenharmony_ci}
688e41f4b71Sopenharmony_ci
689e41f4b71Sopenharmony_ci@ComponentV2
690e41f4b71Sopenharmony_cistruct MyComponent {
691e41f4b71Sopenharmony_ci  @Param count: number | undefined = 0;
692e41f4b71Sopenharmony_ci
693e41f4b71Sopenharmony_ci  build() {
694e41f4b71Sopenharmony_ci    Column() {
695e41f4b71Sopenharmony_ci      Text(`count(${this.count})`)
696e41f4b71Sopenharmony_ci    }
697e41f4b71Sopenharmony_ci  }
698e41f4b71Sopenharmony_ci}
699e41f4b71Sopenharmony_ci```