1# \@Once:初始化同步一次
2
3
4为了实现仅从外部初始化一次、不接受后续同步变化的能力,开发者可以使用\@Once装饰器搭配\@Param装饰器使用。
5
6
7> **说明:**
8>
9> 从API version 12开始,在\@ComponentV2装饰的自定义组件中支持使用\@Once装饰器。
10>
11>当前状态管理(V2试用版)仍在逐步开发中,相关功能尚未成熟,建议开发者尝鲜试用。
12
13
14
15## 概述
16
17\@Once装饰器仅在变量初始化时接受外部传入值进行初始化,当后续数据源更改时,不会将修改同步给子组件:
18
19- \@Once必须搭配\@Param使用,单独使用或搭配其他装饰器使用都是不允许的。
20- \@Once不影响\@Param的观测能力,仅针对数据源的变化做拦截。
21- \@Once与\@Param装饰变量的先后顺序不影响实际功能。
22- \@Once与\@Param搭配使用时,可以在本地修改\@Param变量的值。
23
24## 装饰器使用规则说明
25
26\@Once装饰器作为辅助装饰器,本身没有对装饰类型的要求以及对变量的观察能力。
27
28| \@Once变量装饰器 | 说明                                      |
29| ---------------- | ----------------------------------------- |
30| 装饰器参数       | 无。                                      |
31| 使用条件         | 无法单独使用,必须配合\@Param装饰器使用。 |
32
33
34## 限制条件
35
36- \@Once只能用在\@ComponentV2装饰的自定义组件中且仅能与\@Param搭配使用。
37
38  ```ts
39  @ComponentV2
40  struct CompA {
41    @Param @Once onceParam: string = "onceParam"; // 正确用法
42    @Once onceStr: string = "Once"; // 错误用法,@Once无法单独使用
43    @Local @Once onceLocal: string = "onceLocal"; // 错误用法,@Once不能与@Local一起使用
44  }
45  @Component
46  struct Index {
47    @Once @Param onceParam: string = "onceParam"; // 错误用法
48  }
49  ```
50
51- \@Once与\@Param的先后顺序无关,可以写成\@Param \@Once也可以写成\@Once \@Param。
52
53  ```ts
54  @ComponentV2
55  struct CompA {
56    @Param @Once param1: number;
57    @Once @Param param2: number;
58  }
59  ```
60
61## 使用场景
62
63### 变量仅初始化同步一次
64
65\@Once使用在期望变量仅初始化时同步数据源一次,之后不再继续同步变化的场景。
66
67```ts
68@ComponentV2
69struct CompA {
70  @Param @Once onceParam: string = '';
71  build() {
72  	Column() {
73  	  Text(`onceParam: ${this.onceParam}`)
74  	}
75  }
76}
77@Entry
78@ComponentV2
79struct CompB {
80  @Local message: string = "Hello World";
81  build() {
82  	Column() {
83      Text(`Parent message: ${this.message}`)
84      Button("change message")
85        .onClick(() => {
86          this.message = "Hello Tomorrow";
87        })
88      CompA({ onceParam: this.message })
89  	}
90  }
91}
92```
93
94### 本地修改\@Param变量
95
96当\@Once搭配\@Param使用时,可以解除\@Param无法在本地修改的限制,且修改能够触发UI刷新。此时,使用\@Param \@Once相当于使用\@Local,区别在于\@Param \@Once能够接受外部传入初始化。
97
98```ts
99@ObservedV2
100class Info {
101  @Trace name: string;
102  constructor(name: string) {
103    this.name = name;
104  }
105}
106@ComponentV2
107struct Child {
108  @Param @Once onceParamNum: number = 0;
109  @Param @Once @Require onceParamInfo: Info;
110
111  build() {
112    Column() {
113      Text(`Child onceParamNum: ${this.onceParamNum}`)
114      Text(`Child onceParamInfo: ${this.onceParamInfo.name}`)
115      Button("changeOnceParamNum")
116        .onClick(() => {
117          this.onceParamNum++;
118        })
119      Button("changeParamInfo")
120        .onClick(() => {
121          this.onceParamInfo = new Info("Cindy");
122        })
123    }
124  }
125}
126@Entry
127@ComponentV2
128struct Index {
129  @Local localNum: number = 10;
130  @Local localInfo: Info = new Info("Tom");
131
132  build() {
133    Column() {
134      Text(`Parent localNum: ${this.localNum}`)
135      Text(`Parent localInfo: ${this.localInfo.name}`)
136      Button("changeLocalNum")
137        .onClick(() => {
138          this.localNum++;
139        })
140      Button("changeLocalInfo")
141        .onClick(() => {
142          this.localInfo = new Info("Cindy");
143        })
144      Child({
145        onceParamNum: this.localNum,
146        onceParamInfo: this.localInfo
147      })
148    }
149  }
150}
151```
152
153