1# arkui子系统ChangeLog
2
3
4## cl.arkui.1 编译拦截@Extend/@AnimatableExtend参数个数不符合预期
5
6@Extend/@AnimatableExtend装饰器参数有且仅能有一个。
7
8**变更影响**
9
10当@Extend/@AnimatableExtend装饰器参数有多个时,编译报错。
11
12**错误示例:**
13
14```ts
15// xxx.ets
16
17@Extend(Text, Button)  // 编译报错: @Extend should have one and only one parameter
18function fancy() {
19  .width(100)
20}
21
22@AnimatableExtend(Text, Polyline)  // 编译报错: @AnimatableExtend should have one and only one parameter
23function fancy2() {
24  .height(100)
25}
26
27@Entry
28@Component
29struct Example {
30  build() {
31    Column() {
32      Text('text')
33        .fancy()
34        .fancy2()
35    }
36  }
37}
38```
39
40**关键接口/组件变更**
41
42不涉及
43
44**适配指导**
45
46@Extend和AnimatableExtend装饰器仅能传一个参数。
47
48参考代码如下:
49```ts
50// xxx.ets
51
52@Extend(Text)
53function fancy() {
54  .width(100)
55}
56
57@AnimatableExtend(Text)
58function fancy2() {
59  .height(100)
60}
61
62@Entry
63@Component
64struct Example {
65  build() {
66    Column() {
67      Text('text')
68        .fancy()
69        .fancy2()
70    }
71  }
72}
73```
74
75## cl.arkui.2 编译拦截@Link/@ObjectLink成员变量未从父组件传值
76
77子组件的@Link/@ObjectLink成员变量需要从父组件传值。
78
79**变更影响**
80
81子组件的@Link/@ObjectLink当没有从父组件传值时,编译报错。
82
83**错误示例:**
84
85```ts
86// xxx.ets
87
88@Observed
89class Count {
90  message: string = 'count'
91}
92
93@Entry
94@Component
95struct Parent {
96  @State state1: string = 'state1';
97  @State state2: Count = new Count();
98  build() {
99    Column() {
100      Child()  // 编译报错:Property 'link' in the custom component 'Child' is missing (mandatory to specify).
101               // 编译报错:Property 'objectLink' in the custom component 'Child' is missing (mandatory to specify).
102    }
103  }
104}
105
106@Component
107struct Child {
108  @Link link: string;
109  @ObjectLink objectLink: Count;
110  build() {
111    Column() {
112      Text(this.link)
113        .fontSize(50)
114      Text(this.objectLink.message)
115        .fontSize(50)
116    }
117  }
118}
119```
120
121**关键接口/组件变更**
122
123不涉及
124
125**适配指导**
126
127子组件的@Link/@ObjectLink成员变量需要从父组件传值。
128
129参考代码如下:
130```ts
131// xxx.ets
132
133@Observed
134class Count {
135  message: string = 'count'
136}
137
138@Entry
139@Component
140struct Parent {
141  @State state1: string = 'state1';
142  @State state2: Count = new Count();
143  build() {
144    Column() {
145      Child({link: $state1, objectLink: this.state2})
146    }
147  }
148}
149
150@Component
151struct Child {
152  @Link link: string;
153  @ObjectLink objectLink: Count;
154  build() {
155    Column() {
156      Text(this.link)
157        .fontSize(50)
158      Text(this.objectLink.message)
159        .fontSize(50)
160    }
161  }
162}
163```
164## cl.arkui.3 canvas组件onReady事件行为变更
165
166**说明**
167onReady事件在组件创建完成后或组件大小发生变化时触发,并清空画布。
168
169**示例:**
170```ts
171@Entry
172@Component
173struct OnReadyDiff {
174  @State message: string = 'init '
175  @State isShow: boolean = false
176  @State myHeight: number = 300
177  private settings: RenderingContextSettings = new RenderingContextSettings(true);
178  private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings);
179
180  build() {
181    Row() {
182      Column() {
183        Text(this.message)
184          .fontSize(50)
185          .fontWeight(FontWeight.Bold)
186        Button('ChangePosition')
187          .onClick(()=>{
188            this.isShow = !this.isShow
189          })
190        if (this.isShow) {
191          Button('new button')
192            .height(200)
193        }
194        Button('ChangeHeight')
195          .onClick(()=>{
196            this.myHeight = this.myHeight==300?500:300
197          })
198
199        Canvas(this.context)
200          .width(300)
201          .height(this.myHeight)
202          .backgroundColor('#ffff00')
203          .onReady(() =>{
204            this.context.fillRect(0, 0, 100, 100)
205            this.message += 'a '
206          })
207        Button('draw another')
208          .onClick(()=>{
209            this.context.fillRect(100, 100, 100, 100)
210          })
211      }
212      .width('100%')
213    }
214    .height('100%')
215  }
216}
217```
218
219API version 9:onReady在组件创建完成时触发,位置变化时会触发,组件大小变化时也会触发。
220
221![stack](figures/api9onReady.gif)
222
223API version 10及以后:onReady在组件创建完成时触发,在组件位置变化时不会触发,组件大小变化时会触发。
224
225![stack](figures/api10onReady.gif)
226
227**变更影响**
228
229onReady事件在组件位置发生变化时行为变更,API version 9及以前会触发,API version 10及以后不会触发。
230
231## cl.arkui.4 Margin属性百分比计算变更
232
233当前margin会计算两次,margin的百分比参照在第一次margin计算之后会减去margin的大小,计算完之后百分比类型margin第二次计算时数值偏小。变更后margin第一次计算的结果为最终值,不进行第二次计算。
234
235**变更影响**
236
237所有设置百分比的margin大小。
238
239**错误示例:**
240
241```ts
242// xxx.ets
243@Entry
244@Component
245struct TextInputExample {
246  @State text: string = ''
247  controller: TextInputController = new TextInputController()
248
249  build() {
250    Column(){
251      Row().margin({left:"50%"}).width(100).height(100)
252    }.width("100%").height("100%")
253  }
254}
255```
256
257**关键接口/组件变更**
258
259不涉及
260
261**适配指导**
262
263变更后margin的百分比参照固定为父组件的宽减去父组件的padding且不会减去第一次margin的计算结果,其百分比参照比变更前稍大,建议调整margin百分比的数值。
264
265## cl.arkui.5 ListItem长距离划动接口修改
266
267将ListItem长距离划动接口SwipeActionItem命名中的“Delete”替换为“Action”,同时删除useDefaultDeleteAnimation接口。
268
269**变更影响**
270
271使用OpenHarmony_4.0.9.3以后的SDK版本编译时,需使用变更后接口。
272
273**关键接口/组件变更**
274
275| 变更前接口     |  变更后接口     |
276| ------ | ------------------------------ |
277| deleteAreaDistance   | actionAreaDistance |
278| onDelete   |  onAction |
279| onEnterDeleteArea   | onEnterActionArea |
280| onExitDeleteArea   | onExitActionArea |
281| useDefaultDeleteAnimation | 删除 |
282
283**适配指导**
284
285在使用OpenHarmony_4.0.9.3及以后的SDK版本时,SwipeActionItem需使用变更后接口。OpenHarmony_4.0.9.2及之前版本,SwipeActionItem仍遵循变更前规则。
286
287参考代码如下:
288
289```ts
290// xxx.ets
291@Entry
292@Component
293struct ListItemExample2 {
294  @State message: string = 'Hello World'
295  @State arr: number[] = [0, 1, 2, 3, 4]
296  @State enterEndDeleteAreaString: string = "not enterEndDeleteArea"
297  @State exitEndDeleteAreaString: string = "not exitEndDeleteArea"
298
299  @Builder itemEnd() {
300    Row() {
301      Button("Delete").margin("4vp")
302      Button("Set").margin("4vp")
303    }.padding("4vp").justifyContent(FlexAlign.SpaceEvenly)
304  }
305
306  build() {
307    Column() {
308      List({ space: 10 }) {
309        ForEach(this.arr, (item) => {
310          ListItem() {
311            Text("item" + item)
312              .width('100%')
313              .height(100)
314              .fontSize(16)
315              .textAlign(TextAlign.Center)
316              .borderRadius(10)
317              .backgroundColor(0xFFFFFF)
318          }
319          .transition({ type: TransitionType.Delete, opacity: 0 })
320          .swipeAction({
321            end: {
322              builder: this.itemEnd.bind(this, item),
323              onAction: () => {
324                animateTo({ duration: 1000 }, () => {
325                  let index = this.arr.indexOf(item)
326                  this.arr.splice(index, 1)
327                })
328              },
329              actionAreaDistance: 80,
330              onEnterActionArea: () => {
331                this.enterEndDeleteAreaString = "enterEndDeleteArea"
332                this.exitEndDeleteAreaString = "not exitEndDeleteArea"
333              },
334              onExitActionArea: () => {
335                this.enterEndDeleteAreaString = "not enterEndDeleteArea"
336                this.exitEndDeleteAreaString = "exitEndDeleteArea"
337              }
338            }
339          })
340        }, item => item)
341      }
342      Text(this.enterEndDeleteAreaString).fontSize(20)
343      Text(this.exitEndDeleteAreaString).fontSize(20)
344    }
345    .padding(10)
346    .backgroundColor(0xDCDCDC)
347    .width('100%')
348    .height('100%')
349  }
350}
351```