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