1# arkui子系统ChangeLog
2
3## cl.arkui.1 状态变量数据类型声明使用限制。
4
51. 所有的状态装饰器变量需要显式声明变量类型,不允许声明any。
6
7    示例:
8
9    ```ts
10    // xxx.ets
11    @Entry
12    @Component
13    struct DatePickerExample {
14      // 错误写法: @State isLunar: any = false
15      @State isLunar: boolean = false
16
17      build() {
18   		...
19      }
20    }
21    ```
22
232. @State、@Provide、 @Link和@Consume四种状态变量的数据类型声明只能由简单数据类型或引用数据类型的其中一种构成。
24
25    类型定义中的Length、ResourceStr、ResourceColor三个类型是简单数据类型或引用数据类型的组合,所以不能被以上四种状态装饰器变量使用。
26    Length、ResourceStr、ResourceColor的定义请看文档[arkui-ts类型定义](../../../application-dev/reference/arkui-ts/ts-types.md)。
27
28    示例:
29
30    ```ts
31    // xxx.ets
32    @Entry
33    @Component
34    struct IndexPage {
35      // 错误写法: @State message: string | Resource = 'Hello World'
36      @State message: string = 'Hello World'
37      // 错误写法: @State message: ResourceStr = $r('app.string.hello')
38      @State resourceStr: Resource = $r('app.string.hello')
39
40      build() {
41        Row() {
42          Column() {
43            Text(`${this.message}`)
44              .fontSize(50)
45              .fontWeight(FontWeight.Bold)
46          }
47          .width('100%')
48        }
49        .height('100%')
50      }
51    }
52    ```
53
54    ![hello](../../../application-dev/quick-start/figures/hello.PNG)
55
56**变更影响**
57
581. 如果状态装饰器变量没有显式声明变量类型,声明any,编译拦截会出现警告;
59    ```ts
60    // ArkTS:WARN Please define an explicit type, not any.
61    @State isLunar: any = false
62    ```
633. @State、@Provide、 @Link和@Consume四种状态变量使用框架提供的Length、ResourceStr、ResourceColor,
64    编译拦截报错。
65
66    ```ts
67    /* ArkTS:ERROR The state variable type here is 'ResourceStr', it contains both a simple type and an object type,
68      which are not allowed to be defined for state variable of a struct.*/
69    @State message: ResourceStr = $r('app.string.hello')
70    ```
71
72**关键的接口/组件变更**
73
74不涉及。
75
76**适配指导**
77
781. 状态装饰器变量声明具体的变量类型替代any;
793. 因为Length(string|number|Resource), ResourceStr(string|Resource), ResourceColor(string|number|Color|Resource)
80    的三个类型是简单数据类型或引用数据类型的组合,使用@State、@Provide、 @Link和@Consume四种状态变量场景参考以下修改:
81    ```ts
82    // 错误写法:
83    @State message: ResourceStr = $r('app.string.hello')
84    // 修正后的写法:
85    @State resourceStr: Resource = $r('app.string.hello')
86    ```
87
88## cl.arkui.2 自定义组件成员变量初始化的规则与约束。
89
90通过构造函数方法初始化成员变量,需要遵循如下规则:
91
92| **从父组件中的变量(右)到子组件中的变量(下)** | **regular** | **@State** | **@Link** | **@Prop** | **@Provide** | **@Consume** | **@ObjectLink** |
93| -------------------------- | ----------- | ---------- | --------- | --------- | ------------ | ------------ | --------------- |
94| **regular**                | 支持          | 支持         | 支持        | 支持        | 不支持          | 不支持          | 支持              |
95| **@State**                 | 支持          | 支持         | 支持        | 支持        | 支持           | 支持           | 支持              |
96| **@Link**                  | 不支持         | 支持(1)      | 支持(1)     | 支持(1)     | 支持(1)        | 支持(1)        | 支持(1)           |
97| **@Prop**                  | 支持          | 支持         | 支持        | 支持        | 支持           | 支持           | 支持              |
98| **@Provide**               | 支持          | 支持         | 支持        | 支持        | 支持           | 支持           | 支持              |
99| **@Consume**               | 不支持         | 不支持        | 不支持       | 不支持       | 不支持          | 不支持          | 不支持             |
100| **@ObjectLink**            | 不支持         | 不支持        | 不支持       | 不支持       | 不支持          | 不支持          | 不支持             |
101
102| **从父组件中的变量(右)到子组件中的变量(下)** | **@StorageLink** | **@StorageProp** | **@LocalStorageLink** | **@LocalStorageProp** |
103| -------------------------- | ---------------- | ---------------- | --------------------- | --------------------- |
104| **regular**                | 支持               | 不支持              | 不支持                   | 不支持                   |
105| **@State**                 | 支持               | 支持               | 支持                    | 支持                    |
106| **@Link**                  | 支持(1)            | 支持(1)            | 支持(1)                 | 支持(1)                 |
107| **@Prop**                  | 支持               | 支持               | 支持                    | 支持                    |
108| **@Provide**               | 支持               | 支持               | 支持                    | 支持                    |
109| **@Consume**               | 不支持              | 不支持              | 不支持                   | 不支持                   |
110| **@ObjectLink**            | 不支持              | 不支持              | 不支持                   | 不支持                   |
111
112> **说明**
113>
114> **支持(1)**:必须使用`$`, 例如 `this.$varA`。
115> **regular**:未加修饰的常规变量。
116
117不允许从父组件初始化`@StorageLink`, `@StorageProp`, `@LocalStorageLink`, `@LocalStorageProp`修饰的变量。
118
119**变更影响**
120
1211. 不允许从父组件初始化`@LocalStorageLink`, `@LocalStorageProp`修饰的变量,编译出现警告。
122    ```ts
123    @Entry
124    @Component
125    struct LocalStorageComponent {
126        build() {
127            Column() {
128                Child({
129                  /* ArkTS:WARN Property 'simpleVarName' in the custom component 'Child' cannot
130                    initialize here (forbidden to specify). */
131                  simpleVarName: 1,
132                  /* ArkTS:WARN Property 'objectName' in the custom component 'Child' cannot
133                    initialize here (forbidden to specify). */
134                  objectName: new ClassA("x")
135                })
136            }
137        }
138    }
139    @Component
140    struct Child {
141        @LocalStorageLink("storageSimpleProp") simpleVarName: number = 0;
142        @LocalStorageProp("storageObjectProp") objectName: ClassA = new ClassA("x");
143        build() {}
144    }
145    ```
1462. 子组件的@ObjectLink变量不支持父组件装饰器变量的直接赋值,其父组件的源必须是数组的项或对象的属性,该数组或对象必现用`@State`、`@Link`、`@Provide`、`@Consume`或`@ObjectLink`装饰器修饰。
147    ```ts
148    let NextID : number = 0;
149
150    @Observed class ClassA {
151      public id : number;
152      public c: number;
153      constructor(c: number) {
154        this.id = NextID++;
155        this.c = c;
156      }
157    }
158
159    @Component
160    struct Child {
161      @ObjectLink varA : ClassA;
162      build() {
163        Row() {
164          Text('ViewA-' + this.varA.id)
165        }
166      }
167    }
168
169    @Component
170    struct Parent {
171      @Link linkValue: ClassA
172      build() {
173        Column() {
174          /* ArkTS:ERROR The @Link property 'linkValue' cannot be assigned to
175            the @ObjectLink property 'varA'.*/
176          Child({ varA: this.linkValue })
177        }
178      }
179    }
180    ```
181
182**关键的接口/组件变更**
183
184不涉及。
185
186**适配指导**
1871. 构造子组件时,不对子组件的`@LocalStorageLink`, `@LocalStorageProp`修饰的变量进行。
188    如果需要在父组件中修改子组件的`@LocalStorageLink`, `@LocalStorageProp`修饰的变量,则使用LocalStorage提供的API接口方法(比如set方法)赋值。
1892. @ObjectLink的使用指导请参考文档[@ObjectLink使用指导](../../../application-dev/quick-start/arkts-observed-and-objectlink.md)。
190
191## cl.arkui.3 List组件和Scroll组件onScrollBegin事件变更
192
193List组件和Scroll组件onScrollBegin事件更名为onScrollFrameBegin事件,onScrollBegin事件中dx和dy参数分别表示X轴和Y轴方向滚动偏移量,更变为onScrollFrameBegin事件后使用offset参数表示滚动偏移量。onScrollFrameBegin事件新增ScrollState参数,用于表示当前时手指拖动滑动状态还是惯性滑动状态。
194
195**变更影响**
196
197onScrollBegin事件不能再使用,需要使用onScrollFrameBegin事件。
198
199**关键接口/组件变更**
200
201| 旧事件定义                                    | 新事件定义                                    |
202| ---------------------------------------- | ---------------------------------------- |
203| onScrollBegin(event: (dx: number, dy: number) => { dxRemain: number, dyRemain: number }) | onScrollFrameBegin(event: (offset: number, state: ScrollState) => { offsetRemain: number }) |
204
205onScrollFrameBegin事件说明参考API接口文档:
206- [Scroll组件事件](../../../application-dev/reference/arkui-ts/ts-container-scroll.md#事件)
207- [List组件事件](../../../application-dev/reference/arkui-ts/ts-container-list.md#事件)
208
209**适配指导**
210
211onScrollBegin改成使用onScrollFrameBegin事件,onScrollBegin事件的dx/dy参数改成onScrollFrameBegin事件的offset参数。原本需要更滚动组件的滚动轴来确定是使用dx还dy参数,使用onScrollFrameBegin事件后,只需要直接使用offset参数。
212
213onScrollBegin事件典型使用示例:
214```ts
215@Entry
216@Component
217struct NestedScroll {
218  @State listPosition: number = 0; // 0代表滚动到List顶部,1代表中间值,2代表滚动到List底部。
219  private arr: number[] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
220  private scrollerForScroll: Scroller = new Scroller()
221  private scrollerForList: Scroller = new Scroller()
222
223  build() {
224    Flex() {
225      Scroll(this.scrollerForScroll) {
226        Column() {
227          Text("Scroll Area")
228            .width("100%").height("40%").backgroundColor(0X330000FF)
229            .fontSize(16).textAlign(TextAlign.Center)
230            .onClick(() => {
231              this.scrollerForList.scrollToIndex(5)
232            })
233
234          List({ space: 20, scroller: this.scrollerForList }) {
235            ForEach(this.arr, (item) => {
236              ListItem() {
237                Text("ListItem" + item)
238                  .width("100%").height("100%").borderRadius(15)
239                  .fontSize(16).textAlign(TextAlign.Center).backgroundColor(Color.White)
240              }.width("100%").height(100)
241            }, item => item)
242          }
243          .width("100%")
244          .height("50%")
245          .edgeEffect(EdgeEffect.None)
246          .onReachStart(() => {
247            this.listPosition = 0
248          })
249          .onReachEnd(() => {
250            this.listPosition = 2
251          })
252          .onScrollBegin((dx: number, dy: number) => {
253            if ((this.listPosition == 0 && dy >= 0) || (this.listPosition == 2 && dy <= 0)) {
254              this.scrollerForScroll.scrollBy(0, -dy)
255              return { dxRemain: dx, dyRemain: 0 }
256            }
257            this.listPosition = 1
258            return { dxRemain: dx, dyRemain: dy };
259          })
260
261          Text("Scroll Area")
262            .width("100%").height("40%").backgroundColor(0X330000FF)
263            .fontSize(16).textAlign(TextAlign.Center)
264        }
265      }
266      .width("100%").height("100%")
267    }.width('100%').height('100%').backgroundColor(0xDCDCDC).padding(20)
268  }
269}
270```
271改成onScrollFrameBegin事件参考代码如下:
272```ts
273@Entry
274@Component
275struct NestedScroll {
276  @State listPosition: number = 0; // 0代表滚动到List顶部,1代表中间值,2代表滚动到List底部。
277  private arr: number[] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
278  private scrollerForScroll: Scroller = new Scroller()
279  private scrollerForList: Scroller = new Scroller()
280
281  build() {
282    Flex() {
283      Scroll(this.scrollerForScroll) {
284        Column() {
285          Text("Scroll Area")
286            .width("100%").height("40%").backgroundColor(0X330000FF)
287            .fontSize(16).textAlign(TextAlign.Center)
288            .onClick(() => {
289              this.scrollerForList.scrollToIndex(5)
290            })
291
292          List({ space: 20, scroller: this.scrollerForList }) {
293            ForEach(this.arr, (item) => {
294              ListItem() {
295                Text("ListItem" + item)
296                  .width("100%").height("100%").borderRadius(15)
297                  .fontSize(16).textAlign(TextAlign.Center).backgroundColor(Color.White)
298              }.width("100%").height(100)
299            }, item => item)
300          }
301          .width("100%")
302          .height("50%")
303          .edgeEffect(EdgeEffect.None)
304          .onReachStart(() => {
305            this.listPosition = 0
306          })
307          .onReachEnd(() => {
308            this.listPosition = 2
309          })
310          .onScrollFrameBegin((offset: number, state: ScrollState) => {
311            if ((this.listPosition == 0 && offset >= 0) || (this.listPosition == 2 && offset <= 0)) {
312              this.scrollerForScroll.scrollBy(0, -offset)
313              return { offsetRemain: 0 }
314            }
315            this.listPosition = 1
316            return { offsetRemain: offset };
317          })
318
319          Text("Scroll Area")
320            .width("100%").height("40%").backgroundColor(0X330000FF)
321            .fontSize(16).textAlign(TextAlign.Center)
322        }
323      }
324      .width("100%").height("100%")
325    }.width('100%').height('100%').backgroundColor(0xDCDCDC).padding(20)
326  }
327}
328```