1# ArkUI Subsystem Changelog 2 3## cl.arkui.1 Restrictions on Data Type Declarations of State Variables 4 51. The data types of state variables decorated by state decorators must be explicitly declared. They cannot be declared as **any**. 6 7 Example: 8 9 ```ts 10 // xxx.ets 11 @Entry 12 @Component 13 struct DatePickerExample { 14 // Incorrect: @State isLunar: any = false 15 @State isLunar: boolean = false 16 17 build() { 18 ... 19 } 20 } 21 ``` 22 232. The data type declaration of the **@State**, **@Provide**, **@Link**, or **@Consume** decorated state variables can consist of only one of the primitive data types or reference data types. 24 25 The **Length**, **ResourceStr**, and **ResourceColor** types are combinations of primitive data types or reference data types. Therefore, they cannot be used by the aforementioned types of state variables. 26 For details about the definitions of **Length**, **ResourceStr**, and **ResourceColor**, see [Types](../../../application-dev/reference/apis-arkui/arkui-ts/ts-types.md). 27 28 Example: 29 30 ```ts 31 // xxx.ets 32 @Entry 33 @Component 34 struct IndexPage { 35 // Incorrect: @State message: string | Resource = 'Hello World' 36 @State message: string = 'Hello World' 37 // Incorrect: @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  55 56**Change Impacts** 57 581. If the data type of a state variable decorated by a state decorator is declared as **any**, a build error message will be displayed. 59 ```ts 60 // ArkTS:WARN Please define an explicit type, not any. 61 @State isLunar: any = false 62 ``` 633. If the data type of a **@State**, **@Provide**, **@Link**, and or **@Consume** decorated state variable is Length, **ResourceStr**, or **ResourceColor**, 64 a build error will occur. 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**Key API/Component Changes** 73 74N/A 75 76**Adaptation Guide** 77 781. Explicitly declare the data type for state variables decorated by state decorators. 793. 80 Adapt the **@State**, **@Provide**, **@Link**, and **@Consume** decorated variables based on the following code snippet so that they do not use the **Length(string|number|Resource)**, **ResourceStr(string|Resource)**, and **ResourceColor(string|number|Color|Resource)** types: 81 ```ts 82 // Incorrect: 83 @State message: ResourceStr = $r('app.string.hello') 84 // Corrected: 85 @State resourceStr: Resource = $r('app.string.hello') 86 ``` 87 88## cl.arkui.2 Initialization Rules and Restrictions of Custom Components' Member Variables 89 90Comply with the following rules when using constructors to initialize member variables: 91 92| **From the Variable in the Parent Component (Right) to the Variable in the Child Component (Below)**| **regular** | **@State** | **@Link** | **@Prop** | **@Provide** | **@Consume** | **@ObjectLink** | 93| -------------------------- | ----------- | ---------- | --------- | --------- | ------------ | ------------ | --------------- | 94| **regular** | Supported | Supported | Supported | Supported | Not supported | Not supported | Supported | 95| **@State** | Supported | Supported | Supported | Supported | Supported | Supported | Supported | 96| **@Link** | Not supported | Supported (1) | Supported (1) | Supported (1) | Supported (1) | Supported (1) | Supported (1) | 97| **@Prop** | Supported | Supported | Supported | Supported | Supported | Supported | Supported | 98| **@Provide** | Supported | Supported | Supported | Supported | Supported | Supported | Supported | 99| **@Consume** | Not supported | Not supported | Not supported | Not supported | Not supported | Not supported | Not supported | 100| **@ObjectLink** | Not supported | Not supported | Not supported | Not supported | Not supported | Not supported | Not supported | 101 102| **From the Variable in the Parent Component (Right) to the Variable in the Child Component (Below)**| **@StorageLink** | **@StorageProp** | **@LocalStorageLink** | **@LocalStorageProp** | 103| -------------------------- | ---------------- | ---------------- | --------------------- | --------------------- | 104| **regular** | Supported | Not supported | Not supported | Not supported | 105| **@State** | Supported | Supported | Supported | Supported | 106| **@Link** | Supported (1) | Supported (1) | Supported (1) | Supported (1) | 107| **@Prop** | Supported | Supported | Supported | Supported | 108| **@Provide** | Supported | Supported | Supported | Supported | 109| **@Consume** | Not supported | Not supported | Not supported | Not supported | 110| **@ObjectLink** | Not supported | Not supported | Not supported | Not supported | 111 112> **NOTE** 113> 114> **Supported (1)**: The dollar sign ($) must be used, for example, **this.$varA**. 115> 116> **regular**: refers to a regular variable that is not decorated by any decorator. 117 118**@StorageLink**, **@StorageProp**, **@LocalStorageLink**, and **@LocalStorageProp** variables cannot be initialized from the parent component. 119 120**Change Impacts** 121 1221. **@LocalStorageLink** and **@LocalStorageProp** variables cannot be initialized from the parent component. Otherwise, a build error message will be displayed. 123 ```ts 124 @Entry 125 @Component 126 struct LocalStorageComponent { 127 build() { 128 Column() { 129 Child({ 130 /* ArkTS:WARN Property 'simpleVarName' in the custom component 'Child' cannot 131 initialize here (forbidden to specify). */ 132 simpleVarName: 1, 133 /* ArkTS:WARN Property 'objectName' in the custom component 'Child' cannot 134 initialize here (forbidden to specify). */ 135 objectName: new ClassA("x") 136 }) 137 } 138 } 139 } 140 @Component 141 struct Child { 142 @LocalStorageLink("storageSimpleProp") simpleVarName: number = 0; 143 @LocalStorageProp("storageObjectProp") objectName: ClassA = new ClassA("x"); 144 build() {} 145 } 146 ``` 1472. The **@ObjectLink** decorated variable cannot be directly initialized from a decorated variable in the parent component. The source of the parent component must be an array item or object attribute decorated by **@State**, **@Link**, **@Provide**, **@Consume**, or **@ObjectLink**. 148 ```ts 149 let NextID : number = 0; 150 151 @Observed class ClassA { 152 public id : number; 153 public c: number; 154 constructor(c: number) { 155 this.id = NextID++; 156 this.c = c; 157 } 158 } 159 160 @Component 161 struct Child { 162 @ObjectLink varA : ClassA; 163 build() { 164 Row() { 165 Text('ViewA-' + this.varA.id) 166 } 167 } 168 } 169 170 @Component 171 struct Parent { 172 @Link linkValue: ClassA 173 build() { 174 Column() { 175 /* ArkTS:ERROR The @Link property 'linkValue' cannot be assigned to 176 the @ObjectLink property 'varA'.*/ 177 Child({ varA: this.linkValue }) 178 } 179 } 180 } 181 ``` 182 183**Key API/Component Changes** 184 185N/A 186 187**Adaptation Guide** 1881. When building a child component, do not assign values to the variables decorated by **@LocalStorageLink** and **@LocalStorageProp** in the child component. 189 190 To change these variables from the parent component, use the API provided by the **LocalStorage** (such as the **set** API) to assign values to them. 191 1922. For details about how to use **@ObjectLink**, see [\@Observed and \@ObjectLink Decorators: Observing Property Changes in Nested Class Objects](../../../application-dev/quick-start/arkts-observed-and-objectlink.md). 193 194## cl.arkui.3 Change of the onScrollBegin Event of the \<List> and \<Scroll> Components 195 196The **onScrollBegin** event of the **\<List>** and **\<Scroll>** components is renamed **onScrollFrameBegin**. In the **onScrollBegin** event, the amount to scroll by is indicated by the **dx** and **dy** parameters. In the **onScrollFrameBegin** event, it is indicated by the **offset** parameter. The **onScrollFrameBegin** event adds the **ScrollState** parameter to indicate whether the component is in the finger dragging or inertial scrolling state. 197 198**Change Impacts** 199 200The **onScrollBegin** event is deprecated and must be replaced with the **onScrollFrameBegin** event. 201 202**Key API/Component Changes** 203 204| Old Event | New Event | 205| ---------------------------------------- | ---------------------------------------- | 206| onScrollBegin(event: (dx: number, dy: number) => { dxRemain: number, dyRemain: number }) | onScrollFrameBegin(event: (offset: number, state: ScrollState) => { offsetRemain: number }) | 207 208For details about the **onScrollFrameBegin** event, see the following: 209- [Scroll Events](../../../application-dev/reference/apis-arkui/arkui-ts/ts-container-scroll.md#events) 210- [List Events](../../../application-dev/reference/apis-arkui/arkui-ts/ts-container-list.md#events) 211 212**Adaptation Guide** 213 214Switch the event from **onScrollBegin** to **onScrollFrameBegin**, and use the **offset** parameter in **onScrollFrameBegin**, rather than the **dx** and **dy** parameters in **onScrollBegin**, to indicate the amount to scroll by. 215 216Example of using the **onScrollBegin** event: 217```ts 218@Entry 219@Component 220struct NestedScroll { 221 @State listPosition: number = 0; // 0 indicates scrolling to the top of the list, 1 indicates scrolling to the middle of the list, and 2 indicates scrolling to the bottom of the list. 222 private arr: number[] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] 223 private scrollerForScroll: Scroller = new Scroller() 224 private scrollerForList: Scroller = new Scroller() 225 226 build() { 227 Flex() { 228 Scroll(this.scrollerForScroll) { 229 Column() { 230 Text("Scroll Area") 231 .width("100%").height("40%").backgroundColor(0X330000FF) 232 .fontSize(16).textAlign(TextAlign.Center) 233 .onClick(() => { 234 this.scrollerForList.scrollToIndex(5) 235 }) 236 237 List({ space: 20, scroller: this.scrollerForList }) { 238 ForEach(this.arr, (item) => { 239 ListItem() { 240 Text("ListItem" + item) 241 .width("100%").height("100%").borderRadius(15) 242 .fontSize(16).textAlign(TextAlign.Center).backgroundColor(Color.White) 243 }.width("100%").height(100) 244 }, item => item) 245 } 246 .width("100%") 247 .height("50%") 248 .edgeEffect(EdgeEffect.None) 249 .onReachStart(() => { 250 this.listPosition = 0 251 }) 252 .onReachEnd(() => { 253 this.listPosition = 2 254 }) 255 .onScrollBegin((dx: number, dy: number) => { 256 if ((this.listPosition == 0 && dy >= 0) || (this.listPosition == 2 && dy <= 0)) { 257 this.scrollerForScroll.scrollBy(0, -dy) 258 return { dxRemain: dx, dyRemain: 0 } 259 } 260 this.listPosition = 1 261 return { dxRemain: dx, dyRemain: dy }; 262 }) 263 264 Text("Scroll Area") 265 .width("100%").height("40%").backgroundColor(0X330000FF) 266 .fontSize(16).textAlign(TextAlign.Center) 267 } 268 } 269 .width("100%").height("100%") 270 }.width('100%').height('100%').backgroundColor(0xDCDCDC).padding(20) 271 } 272} 273``` 274Example of using the **onScrollFrameBegin** event: 275```ts 276@Entry 277@Component 278struct NestedScroll { 279 @State listPosition: number = 0; // 0 indicates scrolling to the top of the list, 1 indicates scrolling to the middle of the list, and 2 indicates scrolling to the bottom of the list. 280 private arr: number[] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] 281 private scrollerForScroll: Scroller = new Scroller() 282 private scrollerForList: Scroller = new Scroller() 283 284 build() { 285 Flex() { 286 Scroll(this.scrollerForScroll) { 287 Column() { 288 Text("Scroll Area") 289 .width("100%").height("40%").backgroundColor(0X330000FF) 290 .fontSize(16).textAlign(TextAlign.Center) 291 .onClick(() => { 292 this.scrollerForList.scrollToIndex(5) 293 }) 294 295 List({ space: 20, scroller: this.scrollerForList }) { 296 ForEach(this.arr, (item) => { 297 ListItem() { 298 Text("ListItem" + item) 299 .width("100%").height("100%").borderRadius(15) 300 .fontSize(16).textAlign(TextAlign.Center).backgroundColor(Color.White) 301 }.width("100%").height(100) 302 }, item => item) 303 } 304 .width("100%") 305 .height("50%") 306 .edgeEffect(EdgeEffect.None) 307 .onReachStart(() => { 308 this.listPosition = 0 309 }) 310 .onReachEnd(() => { 311 this.listPosition = 2 312 }) 313 .onScrollFrameBegin((offset: number, state: ScrollState) => { 314 if ((this.listPosition == 0 && offset >= 0) || (this.listPosition == 2 && offset <= 0)) { 315 this.scrollerForScroll.scrollBy(0, -offset) 316 return { offsetRemain: 0 } 317 } 318 this.listPosition = 1 319 return { offsetRemain: offset }; 320 }) 321 322 Text("Scroll Area") 323 .width("100%").height("40%").backgroundColor(0X330000FF) 324 .fontSize(16).textAlign(TextAlign.Center) 325 } 326 } 327 .width("100%").height("100%") 328 }.width('100%').height('100%').backgroundColor(0xDCDCDC).padding(20) 329 } 330} 331``` 332