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  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```