1# ArkUI组件开发常见问题(ArkTS) 2 3 4## 自定义弹窗能否在ts文件中定义和使用(API 9) 5 6自定义弹窗的定义和初始化需要用到属于ArkTS语法内容,必须在ets后缀文件中定义使用,不能在ts后缀文件中定义使用。 7 8**参考链接** 9 10[自定义弹窗](../reference/apis-arkui/arkui-ts/ts-methods-custom-dialog-box.md) 11 12 13## 自定义弹窗中的变量如何传递给页面(API 9) 14 15**问题现象** 16 17在自定义弹窗内定义的变量内容,在关闭弹窗或变量变化时需要及时传递给页面,可以通过何种方式传递? 18 19**解决措施** 20 21- 方式一:使用组件的状态变量传递。 22 23- 方式二:在初始化弹窗时,传递一个方法给自定义弹窗,在自定义弹窗中触发该方法,弹窗中变量作为方法的参数。 24 25- 方式三:使用AppStorage或LocalStorage方式管理页面状态,实现自定义弹窗和页面之间状态的共享。 26 27**代码示例** 28 29- 方式一: 30 31 ``` 32 @CustomDialog 33 struct CustomDialog01 { 34 @Link inputValue: string 35 controller: CustomDialogController 36 build() { 37 Column() { 38 Text('Change text').fontSize(20).margin({ top: 10, bottom: 10 }) 39 TextInput({ placeholder: '', text: this.inputValue }).height(60).width('90%') 40 .onChange((value: string) => { 41 this.inputValue = value 42 }) 43 } 44 } 45 } 46 47 @Entry 48 @Component 49 struct DialogDemo01 { 50 @State inputValue: string = 'click me' 51 dialogController: CustomDialogController = new CustomDialogController({ 52 builder: CustomDialog01({ 53 inputValue: $inputValue 54 }) 55 }) 56 57 build() { 58 Column() { 59 Button(this.inputValue) 60 .onClick(() => { 61 this.dialogController.open() 62 }).backgroundColor(0x317aff) 63 }.width('100%').margin({ top: 5 }) 64 } 65 } 66 ``` 67 68- 方式二: 69 70 ``` 71 @CustomDialog 72 struct CustomDialog02 { 73 private inputValue: string 74 changeInputValue: (val: string) => void 75 controller: CustomDialogController 76 build() { 77 Column() { 78 Text('Change text').fontSize(20).margin({ top: 10, bottom: 10 }) 79 TextInput({ placeholder: '', text: this.inputValue }).height(60).width('90%') 80 .onChange((value: string) => { 81 this.changeInputValue(value) 82 }) 83 } 84 } 85 } 86 87 @Entry 88 @Component 89 struct DialogDemo02 { 90 @State inputValue: string = 'click me' 91 dialogController: CustomDialogController = new CustomDialogController({ 92 builder: CustomDialog02({ 93 inputValue: this.inputValue, 94 changeInputValue: (val: string) => { 95 this.inputValue = val 96 } 97 }) 98 }) 99 100 build() { 101 Column() { 102 Button(this.inputValue) 103 .onClick(() => { 104 this.dialogController.open() 105 }).backgroundColor(0x317aff) 106 }.width('100%').margin({ top: 5 }) 107 } 108 } 109 ``` 110 111- 方式三: 112 113 ``` 114 let storage = LocalStorage.GetShared() 115 @CustomDialog 116 struct CustomDialog03 { 117 @LocalStorageLink('inputVal') inputValue: string = '' 118 controller: CustomDialogController 119 build() { 120 Column() { 121 Text('Change text').fontSize(20).margin({ top: 10, bottom: 10 }) 122 TextInput({ placeholder: '', text: this.inputValue }).height(60).width('90%') 123 .onChange((value: string) => { 124 this.inputValue = value; 125 }) 126 } 127 } 128 } 129 130 @Entry(storage) 131 @Component 132 struct DialogDemo03 { 133 @LocalStorageLink('inputVal') inputValue: string = '' 134 dialogController: CustomDialogController = new CustomDialogController({ 135 builder: CustomDialog03() 136 }) 137 138 build() { 139 Column() { 140 Button(this.inputValue) 141 .onClick(() => { 142 this.dialogController.open() 143 }).backgroundColor(0x317aff) 144 }.width('100%').margin({ top: 5 }) 145 } 146 } 147 ``` 148 149 150## 如何获取组件的宽高(API 9) 151 152**问题现象** 153 154组件的宽高信息用于计算布局区域大小以及偏移量等内容,如何获取宽高信息? 155 156**解决措施** 157 158- 方式一:使用组件区域变化事件onAreaChange,在组件初始化或组件尺寸发生变化时触发。 159 160- 方式二:在点击或触摸事件中,事件的回调信息中存在目标元素的区域信息。 161 162**参考链接** 163 164[组件区域变化事件](../reference/apis-arkui/arkui-ts/ts-universal-component-area-change-event.md),[点击事件](../reference/apis-arkui/arkui-ts/ts-universal-events-click.md),[触摸事件](../reference/apis-arkui/arkui-ts/ts-universal-events-touch.md) 165 166 167## 如何一键清空TextInput、TextArea组件内容(API 9) 168 169**问题现象** 170 171TextInput,TextArea组件输入多字符后,需要实现点击清空。 172 173**解决措施** 174 175将状态变量赋值给TextInput或TextArea组件的text属性,在做点击清空事件时为状态变量赋值空字符串。 176 177**代码示例** 178 179``` 180struct Index { 181@State text: string = 'Hello World' 182controller: TextInputController = new TextInputController() 183 build() { 184 Row() { 185 Column() { 186 TextInput({ placeholder: 'Please input your words.', text: this.text, 187 controller:this.controller}).onChange((value) => { 188 this.text = value 189 }) 190 Button("Clear TextInput").onClick(() => { 191 this.text = ""; 192 }) 193 } 194 .width('100%') 195 } 196 .height('100%') 197 } 198} 199``` 200 201 202## 如何设置自定义弹窗位置(API 9) 203 204**问题现象** 205 206自定义弹窗当前默认在窗口居中显示,当自定义弹窗需要与窗口边框对齐是需要设置自定义弹窗的对齐方式。 207 208**解决措施** 209 210初始化自定义弹窗时,通过alignment参数设置对齐方式,通过offset设置弹窗偏移量。 211 212**参考链接** 213 214[自定义弹窗](../reference/apis-arkui/arkui-ts/ts-methods-custom-dialog-box.md) 215 216 217## 如何隐藏容器组件的溢出内容(API 9) 218 219**问题现象** 220 221当容器组件内容溢出时,表现为子组件边缘超出容器组件,需要进行隐藏设置。 222 223**解决措施** 224 225将通用属性-形状裁剪clip属性设置为true,表示按照容器边缘轮廓进行裁剪。此属性默认为false,表示不进行裁剪隐藏。 226 227**参考链接** 228 229[形状裁剪](../reference/apis-arkui/arkui-ts/ts-universal-attributes-sharp-clipping.md) 230 231 232## 自定义弹窗大小如何自适应内容(API 9) 233 234**问题现象** 235 236当自定义弹窗中存在可变化区域大小的子组件时,弹窗大小需要跟随自适应。 237 238**解决措施** 239 240- 方式一:采用弹窗容器默认样式。在默认样式中,弹窗容器高度自适应子节点,最大可为窗口高度的90%;弹窗容器的宽度根据栅格系统自适应,不跟随子节点变化。 241 242- 方式二:当显示设置customStyle为true时,弹窗宽高跟随子节点内容适应。 243 244**参考链接** 245 246[自定义弹窗](../reference/apis-arkui/arkui-ts/ts-methods-custom-dialog-box.md) 247 248 249## 如何理解自定义弹窗中的gridCount参数(API 9) 250 251gridCount参数是指弹窗宽度占栅格列数的个数。系统把窗口宽等分,等分的份数即为栅格列数,不同设备栅格列数不同。假设设备屏幕密度值在320vp<=水平宽度<600vp,所以栅格列数是4,则gridCount的有效值在[1, 4]。 252 253注意:仅采用弹窗默认样式时设置有效。 254 255**参考链接** 256 257[自定义弹窗](../reference/apis-arkui/arkui-ts/ts-methods-custom-dialog-box.md) 258 259 260## 如何去除自定义弹窗的白色背景(API 9) 261 262**问题现象** 263 264使用自定义弹窗时,默认样式中存在白色背景。 265 266**解决措施** 267 268需要采用自定义样式来消除自定义弹窗的白色背景: 269 2701. 在初始化自定义弹窗时设置customStyle为true。 271 2722. 在定义弹窗时设置组件背景色backgroundColor。 273 274**参考链接** 275 276[自定义弹窗](../reference/apis-arkui/arkui-ts/ts-methods-custom-dialog-box.md) 277 278 279## TextInput组件密码模式下,右边的眼睛图标能否支持自定义(API 9) 280 281**问题现象** 282 283TextInput组件设置type为InputType.Password时,右侧出现眼睛图标,不能修改图标样式。 284 285**解决措施** 286 287当前图标不支持自定义,可使用TextInput的showPasswordIcon属性隐藏图标,使用Image组件替代控制TextInput组件的type。 288 289**参考链接** 290 291[TextInput组件](../reference/apis-arkui/arkui-ts/ts-basic-components-textinput.md) 292 293 294## TextInput的onSubmit事件如何使用(API 9) 295 296**问题现象** 297 298TextInput的onSubmit事件怎么触发,以及事件回调的参数类型代表的含义。 299 300**解决措施** 301 302onSubmit事件在外接键盘或软键盘回车时触发该回调,回调的参数为当前软键盘回车键类型。通过TextInput的enterKeyType属性可以设置输入法回车键类型,软键盘回车键样式需要输入法的支持。 303 304**参考链接** 305 306[TextInput组件](../reference/apis-arkui/arkui-ts/ts-basic-components-textinput.md) 307 308 309## TextInput在聚焦时如何使光标回到起点(API 9) 310 311**问题现象** 312 313TextInput组件在聚焦时,光标位置会自动根据触摸点位置变化,如何使得聚焦时光标固定显示在起点位置? 314 315**解决措施** 316 3171. TextInput组件绑定onEditChange事件,该事件TextInput可进行输入时触发。 318 3192. 在事件回调用TextInputController.caretPosition方法设置光标位置,不过需要用到setTimeout延迟方法。 320 321**代码示例** 322 323``` 324@Entry 325@Component 326struct TextInputDemo { 327 controller: TextInputController = new TextInputController() 328 329 build() { 330 Column() { 331 TextInput({ controller: this.controller }) 332 .onEditChange((isEditing: boolean) => { 333 if (isEditing) { 334 setTimeout(() => { 335 this.controller.caretPosition(0) 336 }, 100) 337 } 338 }) 339 } 340 } 341} 342``` 343 344**参考链接** 345 346[TextInput组件](../reference/apis-arkui/arkui-ts/ts-basic-components-textinput.md) 347 348 349## 如何获取可滚动组件的当前滚动偏移量(API 9) 350 351**问题现象** 352 353可滚动组件包含List,Grid,Scroll等,在发生滚动时如何获取滚动偏移量? 354 355**解决措施** 356 3571. 可滚动组件在初始化时可设置scroller参数,绑定滚动控制器。 358 3592. 通过控制器的currentOffset方法可获取水平和竖直方向的滚动偏移量。 360 361**参考链接** 362 363[Scroll](../reference/apis-arkui/arkui-ts/ts-container-scroll.md#currentoffset) 364 365 366## 如何实现文本竖向排列(API 9) 367 368**问题现象** 369 370使用Text组件时,无法将文本排列方向设置为竖向排列。 371 372**解决措施** 373 374Text组件当前文本排列方向固定为横向排列,要设置为竖向排列,可将文件拆分,使用Flex容器组件装填,设置主轴方向为竖向。 375 376**代码示例** 377 378``` 379@Entry 380@Component 381struct Index15 { 382 private message: string = '本文档适用于应用开发的初学者。通过构建一个简单的具有页面跳转/返回功能的应用,快速了解工程目录的主要文件,熟悉应用开发流程。'; 383 build() { 384 Flex({ direction: FlexDirection.Column, wrap: FlexWrap.Wrap }) { 385 ForEach(this.message.split(''), (item, index) => { 386 Text(item) 387 .fontSize(30) 388 .flexShrink(0) 389 }) 390 } 391 } 392} 393``` 394 395 396## 如何将Ability的UI界面设置成透明(API 9) 397 398**问题现象** 399 400如何设置Ability的UI界面为透明 401 402**解决措施** 403 404将最上层容器组件背景色设置为透明,然后通过设置XComponent组件的opacity属性值为0.01来实现。 405 406示例: 407 408``` 409build() { 410 Stack() { 411 XComponent({ 412 id: 'componentId', 413 type: 'surface', 414 }) 415 .width('100%') 416 .height('100%') 417 .opacity(0.01) 418 // 页面内容 419 } 420 .width('100%') 421 .height('100%') 422 .backgroundColor('rgba(255,255,255, 0)') 423} 424``` 425 426 427## constraintSize尺寸设置不生效(API 9) 428 429适用于Stage模型。 430 431**问题现象** 432 433constraintSize约束组件尺寸时,子组件内设置百分比宽度,例如width('100%')会采用constraintSize约束中的最大宽乘百分比,导致撑开组件,看起来constraintSize设置没生效。 434 435**解决措施** 436 437可以在外层使用Scroll组件,设置constraintSize,当子组件占用空间超过设置的约束值时,会显示滚动条。 438 439 440## 如何将背景颜色设置为透明(API 9) 441 442**解决措施** 443 444将backgroundColor设置为 '\#00000000'。 445 446 447## Scroll组件滚动到达不了最底部(API 9) 448 449适用于Stage模型。 450 451**问题现象** 452 453Scroll组件在未设置高度情况下,默认为窗口高度,当滚动区域外存在其他组件时,滚动底部区域会出现遮挡。 454 455**解决措施** 456 457Scroll组件需要设置Scroll高度,或者使用Flex布局限制Scroll高度。 458 459 460## 如何自定义Video组件控制栏样式(API 9) 461 462适用于Stage模型。 463 464**解决措施** 465 4661. 通过设置属性controls为false关闭默认控制栏。 467 4682. 设置Video组件的controller。 469 4703. 通过ArkTS实现自定义的控制栏,并通过VideoController控制视频播放。 471 472**代码示例** 473 474``` 475// xxx.ets 476@Entry@Componentstruct VideoCreateComponent { 477 @State videoSrc: Resource = $rawfile('video1.mp4') 478 @State previewUri: Resource = $r('app.media.poster1') 479 @State curRate: PlaybackSpeed = PlaybackSpeed.Speed_Forward_1_00_X 480 @State isAutoPlay: boolean = false 481 @State showControls: boolean = true 482 controller: VideoController = new VideoController() 483 build() { 484 Column() { 485 Video({ 486 src: this.videoSrc, 487 previewUri: this.previewUri, 488 currentProgressRate: this.curRate, 489 controller: this.controller 490 }).width('100%').height(600) 491 .autoPlay(this.isAutoPlay) 492 .controls(this.showControls) 493 .onStart(() => { 494 console.info('onStart') 495 }) 496 .onPause(() => { 497 console.info('onPause') 498 }) 499 .onFinish(() => { 500 console.info('onFinish') 501 }) 502 .onError(() => { 503 console.info('onError') 504 }) 505 .onPrepared((e) => { 506 console.info('onPrepared is ' + e.duration) 507 }) 508 .onSeeking((e) => { 509 console.info('onSeeking is ' + e.time) 510 }) 511 .onSeeked((e) => { 512 console.info('onSeeked is ' + e.time) 513 }) 514 .onUpdate((e) => { 515 console.info('onUpdate is ' + e.time) 516 }) 517 Row() { 518 Button('src').onClick(() => { 519 this.videoSrc = $rawfile('video2.mp4') // 切换视频源 520 }).margin(5) 521 Button('previewUri').onClick(() => { 522 this.previewUri = $r('app.media.poster2') // 切换视频预览海报 523 }).margin(5) 524 525 Button('controls').onClick(() => { 526 this.showControls = !this.showControls // 切换是否显示视频控制栏 527 }).margin(5) 528 } 529 Row() { 530 Button('start').onClick(() => { 531 this.controller.start() // 开始播放 532 }).margin(5) 533 Button('pause').onClick(() => { 534 this.controller.pause() // 暂停播放 535 }).margin(5) 536 Button('stop').onClick(() => { 537 this.controller.stop() // 结束播放 538 }).margin(5) 539 Button('setTime').onClick(() => { 540 this.controller.setCurrentTime(10, SeekMode.Accurate) // 精准跳转到视频的10s位置 541 }).margin(5) 542 } 543 Row() { 544 Button('rate 0.75').onClick(() => { 545 this.curRate = PlaybackSpeed.Speed_Forward_0_75_X // 0.75倍速播放 546 }).margin(5) 547 Button('rate 1').onClick(() => { 548 this.curRate = PlaybackSpeed.Speed_Forward_1_00_X // 原倍速播放 549 }).margin(5) 550 Button('rate 2').onClick(() => { 551 this.curRate = PlaybackSpeed.Speed_Forward_2_00_X // 2倍速播放 552 }).margin(5) 553 } 554 } 555 }} 556``` 557 558**参考链接** 559 560[Video](../reference/apis-arkui/arkui-ts/ts-media-components-video.md#start) 561 562## 如何设置组件不同状态下的样式(API 9) 563 564**问题现象** 565 566对应组件的不同状态(如无状态、按下、禁用、聚焦、点击),显示不同的样式。 567 568**解决措施** 569 570使用多态样式,在组件的StateStyles接口中,定义组件不同状态下的样式。 571 572**代码示例** 573 574``` 575//xxx.ts 576@Entry 577@Component 578struct StyleExample { 579 @State isEnable: boolean = true; 580 581 @Styles pressedStyles() { 582 .backgroundColor("#ED6F21") 583 .borderRadius(10) 584 .borderStyle(BorderStyle.Dashed) 585 .borderWidth(2) 586 .borderColor('#33000000') 587 .width(120) 588 .height(30) 589 .opacity(1) 590 } 591 build() { 592 Flex({direction: FlexDirection.Column, alignItems: ItemAlign.Center}) { 593 Text("pressed") 594 .backgroundColor('#0A59F7') 595 .borderRadius(20) 596 .borderStyle(BorderStyle.Dotted) 597 .borderWidth(2) 598 .borderColor(Color.Red) 599 .width(100) 600 .height(25) 601 .opacity(1) 602 .fontSize(14) 603 .fontColor(Color.White) 604 .stateStyles({ 605 pressed: this.pressedStyles 606 }) 607 .margin({ 608 bottom: 20 609 }) 610 .textAlign(TextAlign.Center) 611 } 612 .width(350) 613 .height(300) 614 } 615} 616``` 617 618**参考链接** 619 620[多态样式](../reference/apis-arkui/arkui-ts/ts-universal-attributes-polymorphic-style.md) 621 622## Scroll内Flex加宽高与滑动冲突(API 9) 623 624适用于Stage模型。 625 626**问题现象** 627 628当在Scroll组件中添加容器组件,并设置该容器组件的尺寸时,会破坏滚动布局。 629 630**解决措施** 631 632Scroll组件中的容器组件不设置尺寸,大小由内容撑开。 633 634 635## 父组件中如何处理子组件内点击事件(API 9) 636 637适用于Stage模型。 638 639在父组件中初始化子组件时,将父组件中定义的方法,传递给子组件,在子组件中调用该方法,类似于变量传递。 640 641**代码示例** 642 643``` 644class Model { 645 value: string 646} 647@Entry 648@Component 649struct EntryComponent { 650 test() { 651 console.log('testTag test in my component'); 652 } 653 build() { 654 Column() { 655 MyComponent({ title: { value: 'Hello World 2' }, count: 7, onClick: this.test }) //初始化时传递定义的方法 656 } 657 } 658} 659 660@Component 661struct MyComponent { 662 @State title: Model = { value: 'Hello World' } 663 @State count: number = 0 664 onClick: any; 665 private toggle: string = 'Hello World' 666 private increaseBy: number = 1 667 668 build() { 669 Column() { 670 Text(`${this.title.value}`).fontSize(30) 671 Button(`Click to increase count=${this.count}`) 672 .margin(20) 673 .onClick(() => { 674 // 修改内部状态变量count 675 this.count += this.increaseBy 676 this.onClick.call(); 677 }) 678 } 679 } 680} 681``` 682 683 684## 如何主动拉起软键盘(API 9) 685 686**解决措施** 687 688可以通过focusControl.requestFocus控制输入框获焦,组件获焦后会自动弹起软键盘 689 690**参考链接** 691 692焦点控制:[焦点控制](../reference/apis-arkui/arkui-ts/ts-universal-attributes-focus.md) 693 694 695## SideBarContainer如何设置controlButton属性(API 9) 696 697**解决措施** 698 699示例代码: 700 701``` 702@Entry 703@Component 704struct SideBarContainerExample { 705 normalIcon : Resource = $r("app.media.icon") 706 selectedIcon: Resource = $r("app.media.icon") 707 @State arr: number[] = [1, 2, 3] 708 @State current: number = 1 709 710 build() { 711 SideBarContainer(SideBarContainerType.Embed) 712 { 713 Column() { 714 ForEach(this.arr, (item, index) => { 715 Column({ space: 5 }) { 716 Image(this.current === item ? this.selectedIcon : this.normalIcon).width(64).height(64) 717 Text("Index0" + item) 718 .fontSize(25) 719 .fontColor(this.current === item ? '#0A59F7' : '#999') 720 .fontFamily('source-sans-pro,cursive,sans-serif') 721 } 722 .onClick(() => { 723 this.current = item 724 }) 725 }, item => item) 726 }.width('100%') 727 .justifyContent(FlexAlign.SpaceEvenly) 728 .backgroundColor('#19000000') 729 730 731 Column() { 732 Text('SideBarContainer content text1').fontSize(25) 733 Text('SideBarContainer content text2').fontSize(25) 734 } 735 .margin({ top: 50, left: 20, right: 30 }) 736 } 737 .sideBarWidth(150) 738 .minSideBarWidth(50) 739 .controlButton({left:32, 740 top:32, 741 width:32, 742 height:32, 743 icons:{shown: $r("app.media.icon"), 744 hidden: $r("app.media.icon"), 745 switching: $r("app.media.icon")}}) 746 .maxSideBarWidth(300) 747 .onChange((value: boolean) => { 748 console.info('status:' + value) 749 }) 750 } 751} 752``` 753 754## 如何实现主动控制组件刷新(API 10) 755 756**解决措施** 757 758Canvas组件最终的显示内容分两种,一种是组件通用属性的绘制内容,比如背景色,boarder等这类组件属性方法设置的渲染属性,这类属性是可以通过状态变量驱动更新的。 759另一种是通过CanvasRenderingContext2D绘制接口由应用自行绘制的内容。该类命令时绘制接口不响应状态变量,该类接口内置表脏功能,只要调用就会在下一帧刷新绘制内容,不需要开发者显式刷新。 760 761**参考链接** 762 763[CanvasRenderingContext2D](../reference/apis-arkui/arkui-ts/ts-canvasrenderingcontext2d.md) 764 765## 怎么解决列表组件List在不设置高度的情况下,会出现滑动不到底的问题(API 10) 766 767**原因分析** 768 769List没有设置高度时,如果子组件总高度大于List父组件的高度时,List会取List父组件高度。如果List有其他兄弟节点,可能会吧List部分顶出父组件显示区域外,看起来像是划不到底部。 770 771**解决措施** 772 773List组件设置layoutWeight(1)属性,将剩余空间全部分配给List组件。 774 775**参考链接** 776 777[尺寸设置](../reference/apis-arkui/arkui-ts/ts-universal-attributes-size.md) 778 779## 如何实现瀑布流滑动时,数据的无限加载和显示(API 10) 780 781**解决措施** 782 7831.使用LazyForEach做瀑布流子节点。 784 7852.参考WaterFlow高性能开发指导在FlowItem的onAppear中判断是否即将触底,提前在LazyForEach数据源尾部新增数据;或在onScrollIndex11+事件中根据当前index进行判断。 786 787**参考链接** 788 789[WaterFlow高性能开发指导](../performance/waterflow_optimization.md) 790 791## customDialog中调用router.push启动新页面,会把customDialog关闭,怎么实现在不关闭弹窗的前提下启动新页面(API 10) 792 793**解决措施** 794 795开发者在路由跳转时,需要获取到主窗口的uiContext,再调用路由跳转。 796 797**参考链接** 798 799[自定义弹窗](../reference/apis-arkui/arkui-ts/ts-methods-custom-dialog-box.md) 800 801## 当前ArkUI-X的支持进展如何,有无明确路线图(API 10) 802 803**解决措施** 804 8051.进展:ArkUI-X当前已经开源,首版本已于2023-12-15正式发布,当前支持Android、iOS跨平台;另外,也在探索和试验桌面平台与Web平台的支持。 806 8072.[路线图](https://gitee.com/arkui-x/docs/blob/master/zh-cn/roadmap/ArkUI-X-roadmap-2023.md)。 808 809**参考链接** 810 811[ArkUI-X](https://gitee.com/arkui-x) 812 813## 应用如何在自定义组件的构建流程里跟踪组件数据或者状态(API 10) 814 815**问题现象** 816 817UI的构建build方法内无法插入日志,导致应用无法感知UI绘制流程,不利于调试UI,定位UI问题。 818 819**解决措施** 820 821使用@Watch回调来监测状态变量的变化,如果执行回调函数,说明在下一次vysnc信号发送时,使用该状态变量的UI会刷新绘制。 822 823示例代码如下: 824 825```ts 826@Prop @Watch('onCountUpdated') count: number = 0; 827@State total: number = 0; 828// @Watch 回调 829onCountUpdated(propName: string): void { 830 this.total += this.count; 831} 832``` 833 834**参考链接** 835 836[@Watch装饰器:状态变量更改通知](../quick-start/arkts-watch.md) 837 838## 自定义component不支持继承语法,针对其他框架支持的自定义组件继承及封装能力,ArkUI的解决方案是什么(API 10) 839 840**解决措施** 841 842对于声明式的自定义组件场景,不会提供继承的能力,需要使用组合的方式进行扩展,并结合后续提供的Modifier机制进行对现有组件属性的继承、复用和传递。 843 844## 组件支持的参数类型及参数单位类型区别是什么,使用场景是什么(API 10) 845 846**解决措施** 847 848屏幕像素单位px(pixel),表示屏幕上的实际像素,1px代表设备屏幕上的一个像素点。视窗逻辑像素单位lpx,lpx单位为实际屏幕宽度与逻辑宽度(通过designWidth配置)的比值,标识页面设计基准宽度。以此为基准,根据实际设备宽度来缩放元素大小。距离使用vp(virtual pixel),字体大小使用fp(font pixel),虚拟像素单位vp(virtual pixel),vp具体计算公式为:vp= px/(DPI/160)。 849以屏幕相对像素为单位, 是一台设备针对应用而言所具有的虚拟尺寸(区别于屏幕硬件本身的像素单位)。它提供了一种灵活的方式来适应不同屏幕密度的显示效果,使用虚拟像素,使元素在不同密度的设备上具有一致的视觉体量。字体像素单位fp(font pixel),字体像素(font pixel)大小默认情况下与vp相同,即默认情况下1fp=1vp。如果用户在设置中选择了更大的字体,字体的实际显示大小就会在vp的基础上乘以scale系数,即1fp=1vp*scale。Percentage - 需要指定以%像素单位,如'10%'。 850Resource - 资源引用类型,引入系统资源或者应用资源中的尺寸。 851