1# ArkTS语法使用常见问题 2 3 4## ArkUI如何通过代码动态创建组件(API 9) 5 6**解决措施** 7 8ArkUI使用ArkTS声明式开发范式,开发者无法持有组件实例,在声明时通过渲染控制语法以及动态构建UI元素的方式,控制组件的创建。 9 10**代码示例** 11 12``` 13// 条件渲染语句创建组件 14if(this.isTrue) { 15 Text("创建文本组件").fontSize(30) 16} 17// 循环渲染语句创建组件 18ForEach(this.nums,(item) => { 19 Text(item + '').fontSize(30) 20},item => JSON.stringify(item)) 21``` 22 23**参考链接** 24 25[渲染控制语法](../quick-start/arkts-rendering-control-overview.md) 26 27 28## 使用\@Builder装饰器包含自定义组件的方法与普通方法的区别是什么(API 9) 29 30**解决措施** 31 32\@Builder装饰的方法中使用了自定义组件,那么该方法每次被调用时,对应的自定义组件均会重新创建,普通方法中不使用\@builder装饰,无法容纳自定义组件。 33 34**参考链接** 35 36[@BuilderParam](../quick-start/arkts-builderparam.md) 37 38 39## 如何使用\@BuilderParam装饰器进行组件传参(API 9) 40 41**解决措施** 42 43- 不带参数 44 45 对\@BuilderParam修饰的属性进行赋值时不带参数(如:content: this.specificParam),则此属性的类型需定义成无返回值的函数(如:\@BuilderParam content: () => void)。 46 47- 带参数 48 49 对\@BuilderParam修饰的属性进行赋值时带参数(如:callContent: this.specificParam1("111")),则此属性的类型需定义成any(如:\@BuilderParam callContent: any)。 50 51**参考链接** 52 53[@BuilderParam](../quick-start/arkts-builderparam.md) 54 55 56## 如何监听数组内对象属性变化(API 9) 57 58**问题现象** 59 60数组内存储对象示例,需要对对象的属性变化进行监听。 61 62**解决措施** 63 64通过\@Observed配合\@ObjectLink装饰符实现。\@Observed用于类,\@ObjectLink用于变量。 65 66**代码示例** 67 681. 在类上使用\@Observed。 69 70 ``` 71 @Observed 72 class ClassA { 73 public name: string 74 public c: number 75 public id: number 76 77 constructor(c: number, name: string = 'OK') { 78 this.name = name 79 this.c = c 80 } 81 } 82 ``` 83 842. 在组件变量使用\@ObjectLink。 85 86 ``` 87 @Component 88 struct ViewA { 89 label: string = 'ViewA1' 90 @ObjectLink a: ClassA 91 92 build() { 93 Row() { 94 Button(`ViewA [${this.label}] this.a.c= ${this.a.c} +1`) 95 .onClick(() => { 96 this.a.c += 1 97 }) 98 }.margin({ top: 10 }) 99 } 100 } 101 ``` 102 103**参考链接** 104 105[Observed和ObjectLink数据管理](../quick-start/arkts-observed-and-objectlink.md) 106 107 108## 子组件使用\@Link修饰成员变量时,如何通过父组件传值(API 9) 109 110**解决措施** 111 112子组件使用\@Link接受父组件的值时,需要使用'$'建立变量之间的引用关系。才能实现同步。 113 114**代码示例** 115 116\@Link语义是从'$'操作符引出,即$isPlaying是this.isPlaying内部状态的双向数据绑定。当单击子组件PlayButton中的按钮时,\@Link变量更改,PlayButton与父组件中的Text和Button将同时进行刷新,同样地,当点击父组件中的Button修改this.isPlaying时,子组件PlayButton与父组件中的Text和Button也将同时刷新。 117 1181. 在父组件使用\@State装饰器,传递数据使用$符创建引用。 119 120 ``` 121 @Entry 122 @Component 123 struct Player { 124 @State isPlaying: boolean = false 125 build() { 126 Column() { 127 PlayButton({ buttonPlaying: $isPlaying }) 128 Text(`Player is ${this.isPlaying ? '' : 'not'} playing`).fontSize(18) 129 Button('Parent:' + this.isPlaying) 130 .margin(15) 131 .onClick(() => { 132 this.isPlaying = !this.isPlaying 133 }) 134 } 135 } 136 } 137 138 ``` 139 1402. 在子组件使用\@Link接受数据。 141 142 ``` 143 @Component 144 struct PlayButton { 145 @Link buttonPlaying: boolean 146 147 build() { 148 Column() { 149 Button(this.buttonPlaying ? 'pause' : 'play') 150 .margin(20) 151 .onClick(() => { 152 this.buttonPlaying = !this.buttonPlaying 153 }) 154 } 155 } 156 } 157 ``` 158 159**参考链接** 160 161[@Link](../quick-start/arkts-link.md) 162 163 164## 父组件如何与孙子组件进行状态同步(API 9) 165 166**解决措施** 167 168- 方式一(推荐):使用\@Provide和\@Consume装饰器。在父组件使用\@Provide,在孙子组件使用\@Consume,可以实现父组件和孙子组件进行双向数据绑定。 169 170- 方式二:使用\@State和\@Link装饰器。在父组件使用\@State,在每一层子组件(子组件和孙子组件)都使用\@Link。 171 172**代码示例一** 173 1741. 父组件中使用子组件,通过Provide提供reviewVote参数,供跨级传递给孙子组件。 175 176 ``` 177 @Entry 178 @Component 179 struct Father{ 180 @Provide("reviewVote") reviewVotes: number = 0; 181 182 build() { 183 Column() { 184 Son() 185 Button(`Father: ${this.reviewVotes}`) 186 ... 187 } 188 } 189 } 190 ``` 191 1922. 子组件中使用孙组件。 193 194 ``` 195 @Component 196 struct Son{ 197 build() { 198 Column() { 199 GrandSon() 200 } 201 } 202 } 203 ``` 204 2053. 孙子组件中使用Consume来接受reviewVote的参数。 206 207 ``` 208 @Component 209 struct GrandSon{ 210 @Consume("reviewVote") reviewVotes: number 211 212 build() { 213 Column() { 214 Button(`GrandSon: ${this.reviewVotes}`) 215 ... 216 }.width('100%') 217 } 218 } 219 ``` 220 221**代码示例二** 222 2231. 父组件Father使用\@State绑定数据reviewVote。 224 225 ``` 226 @Entry 227 @Component 228 struct Father { 229 @State reviewVotes: number = 0; 230 231 build() { 232 Column() { 233 Son({reviewVotes:$reviewVotes}) 234 Button(`Father: ${this.reviewVotes}`) 235 ... 236 } 237 } 238 } 239 ``` 240 2412. 子组件Son中使用\@Link接受由父组件Father传递的参数reviewVote。 242 243 ``` 244 @Component 245 struct Son{ 246 @Link reviewVotes: number; 247 build() { 248 Column() { 249 Grandson({reviewVotes:$reviewVotes}) 250 } 251 } 252 } 253 254 ``` 255 2563. 孙子组件GrandSon使用\@Link接受由Son组件传递的参数reviewVote。 257 258 ``` 259 @Component 260 struct Grandson{ 261 @Link reviewVotes: number; 262 263 build() { 264 Column() { 265 Button(`Grandson: ${this.reviewVotes}`) 266 ... 267 }.width('100%') 268 } 269 } 270 ``` 271 272 273## Js如何定义callback函数(API 9) 274 275**解决措施** 276 277定义个callback函数的样例,**示例如下:** 278 2791. 定义回调函数 280 281 ``` 282 // 页面中定义个2个参数,空返回的callback函数 283 myCallback: (a:number,b:string) => void 284 ``` 285 2862. 在使用时进行初始化赋值 287 288 ``` 289 aboutToAppear() { 290 // callback函数初始化 291 this.myCallback= (a,b)=>{ 292 console.info(`handle myCallback a=${a},b=${b}`) 293 }} 294 ``` 295 296 297## 组件需要多次更新时如何优化性能(API 9) 298 299**解决措施** 300 301使用状态管理模块,目前已经支持最小化更新,当数据依赖变化时,不再是重新刷新整个自定义组件,而是只更新依赖数据的视图内容。 302 303 304## 对象中函数的this如何指向外层(API 9) 305 306**解决措施** 307 308通过箭头函数实现。 309 310**代码示例** 311 312``` 313const obj = { 314 start:() => { 315 return this.num 316 } 317} 318``` 319 320 321## 如何实现页面加载前从接口获取数据(API 9) 322 323**问题现象** 324 325页面生命周期相关问题,在页面渲染前从接口获取数据,渲染时将数据渲染到页面上。 326 327**解决措施** 328 329在声明周期函数aboutToAppear中使用异步接口获取页面数据,数据变量使用\@State修饰,数据获取完成后根据变量自动刷新页面。 330 331**代码示例** 332 333``` 334@Entry 335@Component 336struct Test6Page { 337 // 数据获取成功,会自动刷新页面 338 @State message: string = 'loading.....' 339 aboutToAppear(){ 340 // 模拟异步接口获取数据 341 setTimeout(()=>{ 342 this.message = 'new msg' 343 },3000) 344 } 345 build() { 346 Row() { 347 Column() { 348 Text(this.message) 349 .fontSize(50) 350 .fontWeight(FontWeight.Bold) 351 } 352 .width('100%') 353 } 354 .height('100%') 355 } 356} 357``` 358 359 360## 如何将传感器的数据实时显示在UI的Text中(API 9) 361 362**解决措施** 363 364传感器返回数据类型为double,可将double转为string,再显示在text中。 365 366 367## 如何监听屏幕旋转(API 9) 368 369**解决措施** 370 371屏幕旋转可使用媒体查询接口进行监听。 372 373``` 374import mediaquery from '@ohos.mediaquery' 375let listener = mediaquery.matchMediaSync('(orientation: landscape)'); //监听横屏事件 376function onPortrait(mediaQueryResult) { 377 if (mediaQueryResult.matches) { 378 // do something here 379 } else { 380 // do something here 381 } 382} 383listener.on('change', onPortrait) // 注册回调 384listener.off('change', onPortrait) // 去注册回调 385``` 386 387**参考链接** 388 389[媒体查询](../reference/apis-arkui/js-apis-mediaquery.md) 390 391 392## 创建的单例换了页面后不生效问题(API 9) 393 394**问题现象** 395 396单例只有在同一个流程中才有效,换了页面后之前的实例都全是undefined。 397 398**解决措施** 399 400对于每个Page都会生成一个js文件,定义的单例会在每个js中都生成一份,所以单例的作用范围只是Page的范围。 401 402如果想共享一个实例,创建范围需要提升至UIAbility或者App级别。 403 404 405## 如何将时间格式的字符串string转换为Date对象(API 9) 406 407**解决措施** 408 409如果字符string满足格式“yyyy-MM-dd”格式,则可直接使用函数new Date("yyyy-MM-dd")来获取对应的Date对象。 410 411``` 412new Date("2021-05-23"); 413new Date("2020/2/29"); 414new Date("2020-14-03"); 415new Date("14-02-2021"); 416``` 417 418其他格式字符串可使用new Date(year:number,month:number,day?:number,hour?:number,mintue?:number,second?:number,ms?:number)方法来获取Date对象。 419 420``` 421// 根据参数创建日期的语法: 422new Date(yearValue, IndexOfMonth, dayValue, hours, minutes, seconds) 423``` 424 425其中每一个参数换算为对应时间参数传入即可。 426 427- yearValue:应符合 ISO 8061 YYYY 格式。例如 2021。如果我们以 YY 格式指定一个值,它将会被错误地接受。例如,仅将 2021 提到 21 会被认为是 1921 年而不是 2021 年。 428 429- IndexOfMonth:从索引 0 开始。因此,从 Month 值中减去 1。例如,对于 3 月,该值为 3,但 monthIndex 将为 2(即 3-1 = 2)。本月指数通常应在 0-11 范围内 430 431- dayValue:表示一个月中的某天。它应在 1-31 范围内,具体取决于一个月中的天数。例如:对于 21-05-2021,日期值为 21 432 433- hours:一天中的小时。例如 10 点。 434 435- minutes:过去一个小时的分钟数 436 437- seconds:保留超过一分钟的秒数。 438 439 440## ArkTS如何把string转为byte数组(API 9) 441 442**解决措施** 443 444参考如下代码实现,示例: 445 446``` 447stringToArray(str:string) { 448 var arr = []; 449 for(var i = 0,j = str.length;i<j;++i) { 450 arr.push(str.charCodeAt(i)) 451 } 452 return arr; 453} 454``` 455 456 457## ArkTS如何实现字符串编解码(API 9) 458 459**解决措施** 460 461通过util工具函数模块中的TextEncoder和TextDecoder进行解码。 462 463**参考链接** 464 465[TextEncoder](../reference/apis-arkts/js-apis-util.md#textencoder)、[TextDecoder](../reference/apis-arkts/js-apis-util.md#textdecoder) 466 467 468## 如何导入和导出namespace命名空间(API 9) 469 470**解决措施** 471 472通过export和import导入导出 473 474- namespace导数据库出 475 476 ``` 477 namespace Util{ 478 export function getTime(){ 479 return Date.now() 480 } 481 } 482 export default Util 483 ``` 484 485- namespace导入 486 487 ``` 488 import Util from './util' 489 Util.getTime() 490 ``` 491 492 493## worker线程中能否进行关系型数据库的操作(API 9) 494 495当前不支持将UI主线程中的rdb数据库对象发送给Worker线程后进行操作。Worker线程中使用rdb数据库,需要重新获取rdb数据库的对象。 496 497 498## 如何获取应用resource目录下的文件(API 9) 499 500**解决措施** 501 502- 方式一:使用$r或者$rawfile访问。适合静态访问,程序运行时不改变资源路径。 503 504- 方式二:使用ResourceManage访问。适合动态访问,程序运行时可动态改变资源路径。 505 506**参考链接** 507 508[资源访问](../quick-start/resource-categories-and-access.md)与[资源管理](../reference/apis-localization-kit/js-apis-resource-manager.md) 509 510 511## XML格式如何转为JSON格式(API 9) 512 513**问题现象** 514 515服务端返回的数据是通过base64编码后XML格式,需要转为JSON格式进行后续的处理。 516 517**解决措施** 518 519使用util工具中的base64相关接口进行解码操作,然后使用convertxml组件解析XML格式数据。 520 521**代码示例** 522 523``` 524import convertxml from '@ohos.convertxml'; 525import util from '@ohos.util'; 526 527@Entry 528@Component 529struct Faq_4_31 { 530 @State message: string = 'base64转json' 531 532 build() { 533 Row() { 534 Column() { 535 Text(this.message) 536 .fontSize(50) 537 .fontWeight(FontWeight.Bold) 538 .onClick(() => { 539 /* 原数据,GBK编码 540 <?xml version="1.0" encoding="GBK"?> 541 <data> 542 <asset_no>xxxxx</asset_no> 543 <machine_sn>xxxx</machine_sn> 544 <bios_id>xxxx</bios_id> 545 <responsible_emp_name><![CDATA[xxxx]]></responsible_emp_name> 546 <responsible_account><![CDATA[xxxx xxxx]]></responsible_account> 547 <responsible_emp_no>xxxx</responsible_emp_no> 548 <responsible_dept><![CDATA[xxxx]]></responsible_dept> 549 <user_dept><![CDATA[xxxx]]></user_dept> 550 <user_name><![CDATA[xxx]]></user_name> 551 <cur_domain_account>xxxx</cur_domain_account> 552 <asset_loc><![CDATA[--]]></asset_loc> 553 <asset_loc_cur><![CDATA[]]></asset_loc_cur> 554 <asset_type>1</asset_type> 555 <asset_use>For Outsourcing Staff/xxxx</asset_use> 556 <overdue_date></overdue_date> 557 <asset_status>xxxx</asset_status> 558 <asset_period>xxxx</asset_period> 559 <license></license> 560 </data> 561 */ 562 let src = 'PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iR0JLIj8+CjxkYXRhPgo8YXNzZXRfbm8+eHh4eHg8L2Fzc2V0X25vPgo8bWFjaGluZV9zbj54eHh4PC9tYWNoaW5lX3NuPgo8Ymlvc19pZD54eHh4PC9iaW9zX2lkPgo8cmVzcG9uc2libGVfZW1wX25hbWU+PCFbQ0RBVEFbeHh4eF1dPjwvcmVzcG9uc2libGVfZW1wX25hbWU+CjxyZXNwb25zaWJsZV9hY2NvdW50PjwhW0NEQVRBW3h4eHggeHh4eF1dPjwvcmVzcG9uc2libGVfYWNjb3VudD4KPHJlc3BvbnNpYmxlX2VtcF9ubz54eHh4PC9yZXNwb25zaWJsZV9lbXBfbm8+CjxyZXNwb25zaWJsZV9kZXB0PjwhW0NEQVRBW3h4eHhdXT48L3Jlc3BvbnNpYmxlX2RlcHQ+Cjx1c2VyX2RlcHQ+PCFbQ0RBVEFbeHh4eF1dPjwvdXNlcl9kZXB0Pgo8dXNlcl9uYW1lPjwhW0NEQVRBW3h4eF1dPjwvdXNlcl9uYW1lPgo8Y3VyX2RvbWFpbl9hY2NvdW50Pnh4eHg8L2N1cl9kb21haW5fYWNjb3VudD4KPGFzc2V0X2xvYz48IVtDREFUQVstLV1dPjwvYXNzZXRfbG9jPgo8YXNzZXRfbG9jX2N1cj48IVtDREFUQVtdXT48L2Fzc2V0X2xvY19jdXI+Cjxhc3NldF90eXBlPjE8L2Fzc2V0X3R5cGU+Cjxhc3NldF91c2U+Rm9yIE91dHNvdXJjaW5nIFN0YWZmL3h4eHg8L2Fzc2V0X3VzZT4KPG92ZXJkdWVfZGF0ZT48L292ZXJkdWVfZGF0ZT4KPGFzc2V0X3N0YXR1cz54eHh4PC9hc3NldF9zdGF0dXM+Cjxhc3NldF9wZXJpb2Q+eHh4eDwvYXNzZXRfcGVyaW9kPgo8bGljZW5zZT48L2xpY2Vuc2U+CjwvZGF0YT4=' 563 let base64 = new util.Base64Helper(); 564 // base解码 565 let src_uint8Array = base64.decodeSync(src); 566 // 解码为utf-8的字符串 567 let textDecoder = util.TextDecoder.create("utf-8",{ignoreBOM: true}) 568 let src_str = textDecoder.decodeWithStream(src_uint8Array) 569 //替换encoding字段 570 src_str = src_str.replace("GBK","utf-8") 571 console.log('Test src_str: ' + JSON.stringify(src_str)); 572 // 转换 xml-> json 573 let conv = new convertxml.ConvertXML(); 574 let options = {trim : false, declarationKey:"_declaration", 575 instructionKey : "_instruction", attributesKey : "_attributes", 576 textKey : "_text", cdataKey:"_cdata", doctypeKey : "_doctype", 577 commentKey : "_comment", parentKey : "_parent", typeKey : "_type", 578 nameKey : "_name", elementsKey : "_elements"} 579 let src_json = JSON.stringify(conv.convertToJSObject(src_str, options)); 580 console.log('Test json: ' + JSON.stringify(src_json)); 581 }) 582 } 583 .width('100%') 584 } 585 .height('100%') 586 } 587} 588``` 589 590 591## 在生成器函数中编译TS语言有哪些使用限制(API 9) 592 593**解决措施** 594 595TS语言的使用在生成器函数中存在以下限制: 596 597- 表达式仅允许在字符串(${expression})、if条件、ForEach的参数和组件的参数中使用。 598 599- 这些表达式中的任何一个都不能导致任何应用程序状态变量(\@State、\@Link、\@Prop)的改变,否则会导致未定义和潜在不稳定的框架行为。 600 601- 生成器函数内部不能有局部变量。 602 603上述限制都不适用于事件处理函数(例如onClick)的匿名函数实现。 604 605 606## 如何设置一张图片上面四个角都分别有一个角标(API 9) 607 608**问题现象** 609 610应用需求,在一张图片上面四个角分别设置一个角标。 611 612**解决措施** 613 614可以使用绝对定位,设置元素锚点相对于父容器顶部起点的偏移位置。在布局容器中,设置该属性不影响父容器布局。 615 616示例: 617 618``` 619@Entry 620@Component 621struct PositionExample2 { 622 build() { 623 Column({ space: 20 }) { 624 Stack({ alignContent: Alignment.TopStart }) { 625 Row() 626 .size({ width: '100', height: '100' }) 627 .backgroundColor(0xdeb887) 628 Image($r('app.media.app_icon')) 629 .size({ width: 25, height: 25 }) 630 .markAnchor({ x: 0, y: 0 }) 631 Image($r('app.media.app_icon')) 632 .size({ width: 25, height: 25 }) 633 .markAnchor({ x: 25, y: 25 }) 634 .position({ x: '100%', y: '100%' }) 635 }.margin({ top: 25 }).width('100').height('100') 636 } 637 .width('100%').margin({ top: 25 }) 638 } 639} 640``` 641 642 643## util.generateRandomUUID参数问题(API 9) 644 645**解决措施** 646 647generateRandomUUID底层使用Node.js crypto.randomUUID()接口,传递参数为false时会生成uuid,并缓存到系统里,参数为true时使用系统已缓存的UUID。 648 649**参考链接** 650 651参考文档:[util.generateRandomUUID](../reference/apis-arkts/js-apis-util.md#utilgeneraterandomuuid9) 652 653 654## worker线程与主线程是否运行在相同的全局上下文中(API 9) 655 656**解决措施** 657 658worker线程与主线程不在同一个上下文中,它们使用数据通信的方式交互。 659 660**参考链接** 661 662worker:[启动一个Worker](../reference/apis-arkts/js-apis-worker.md) 663 664 665## 应用图标一多设置(API 9) 666 667**问题现象** 668 669希望可以按照设备的不同类型,显示相应的应用图标 670 671**解决措施** 672 673借助资源限定词能力,可以实现应用图标的一多配置 674 675**示例代码** 676 6771.创建资源目录,并在资源目录中添加资源文件,以Tablet为例,在src/main/resources下创建tablet资源目录,在tablet目录下创建media资源文件夹 678 679``` 680├─base 681│ ├─element 682│ ├─media 683│ └─profile 684├─rawfile 685├─tablet 686│ ├─element 687│ └─media 688``` 689 6902.在1中创建的media文件夹下添加设备类型为tablet时希望显示的图标文件,在UI界面进行引用 691 692``` 693@Entry @Component struct Index { build() { 694 Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) { 695 Text($r("app.string.my_string")) 696 .fontSize($r("app.float.my_float")) 697 .fontColor($r("app.color.my_color")) 698 Image($r("app.media.my_image")) 699 .width(100) 700 .height(100) 701 } 702 .width('100%') 703 .height('100%') } } 704``` 705 706**参考链接** 707 708[资源使用](../key-features/multi-device-app-dev/resource-usage.md) 709 710 711## 调用方法的时候,如何解决方法内部的this变成undefined(API 9) 712 713**问题现象** 714 715ArkTS里的this指向 716 717**解决措施** 718 719方式一:在调用方法的时候加上.bind(this); 720 721方式二:使用箭头函数。 722 723 724## systemTime.getCurrentTime()接口和JS的new Date().getTime()有区别吗(API 9) 725 726**解决措施** 727 728systemTime.getCurrentTime(false)和new Date().getTime()一样,都是返回1970年1月1日至今的毫秒数;systemTime.getCurrentTime(true)返回1970年1月1日至今的纳秒数。两种方式都是系统时间。 729 730 731## 如何实现类似js中的slot插槽功能(API 9) 732 733**解决措施** 734 735该功能在ArkTS中使用\@Build和\@BuilderParam方式来实现。 736 737**参考链接** 738 739[@BuilderParam装饰器:引用@Builder函数](../quick-start/arkts-builderparam.md) 740 741 742## 加上lineHeight,Text垂直不居中的原因(API 9) 743 744**原因分析** 745 746Text组件不用设置lineHeight属性,默认就是居中的。绘制文本是从底部开始绘制的,设置合适的lineHeight可以让文本有居中效果,但如果lineHeight设置的过高,文本就会显得偏下一些,一般lineHeight属性用来联合padding属性调整Text内的上下行间距。 747 748**参考链接** 749 750[Text](../reference/apis-arkui/arkui-ts/ts-basic-components-text.md#示例1) 751 752 753## 使用什么接口进行url编码(API 9) 754 755**解决措施** 756 757使用全局函数encodeURI进行编码,使用decodeURI进行解码。例如空格字符““,编码后为%20。 758 759``` 760let a = encodeURI(" ") 761console.log(a) // %20 762``` 763 764 765## 如何解析xml(API 9) 766 767**解决措施** 768 769使用ConvertXML的convert接口可以将xml文本解析为JavaScript对象。 770 771**参考链接** 772 773[转换xml](../reference/apis-arkts/js-apis-convertxml.md) 774 775 776## 使用Styles装饰器,编译报错.stateStyles doesn't conform standard(API 9) 777 778**原因分析** 779 780Styles装饰器内部只支持通用属性,使用了非通用属性作为Style的代码 781 782**解决措施** 783 784去掉非通用属性,或者使用Builder来提取公共组件。 785 786 787## Radio组件$$双向绑定(API 9) 788 789**解决措施** 790 791Radio组件使用$$绑定的变量变更时,仅渲染当前组件,提高渲染速度。 792 793当Radio组件的状态发生改变时,不会自动修改绑定的变量。 794 795**参考链接** 796 797[内置组件双向同步](../quick-start/arkts-two-way-sync.md) 798 799## ForEach组件在真机上无法执行(API 9) 800 801**问题现象** 802 803ForEach组件预览器可以正常执行,但在真机上无法执行。 804 805**原因分析** 806 807真机上系统版本大于等于3.2beta5版本,真机会默认开启最小化更新策略。 808 809旧版IDE默认没有开启最小化更新,导致组件运行异常。 810 811**解决措施** 812 813module.json5添加"metadata"配置项: 814 815``` 816{ 817 "module": { 818 "metadata": [ 819 { 820 "name": "ArkTSPartialUpdate", 821 "value": "true" 822 } ] 823 } 824} 825``` 826 827## AppStorage是不是不支持线程间共享对象,为什么,推荐替代方案是什么(API 10) 828 829**解决措施** 830 831AppStorage是应用全局的UI状态存储,是和应用的进程绑定的,由UI框架在应用程序启动时创建,为应用程序UI状态属性提供中央存储。 832 833AppStorage支持应用的主线程内多个UIAbility实例间的状态共享。 834 835AppStorage是UI相关的数据,需要运行在UI线程,无法将对象共享到其他线程。目前暂无替代方案。 836 837**参考链接** 838 839[AppStorage:应用全局的UI状态存储](../quick-start/arkts-appstorage.md) 840 841## 自定义字体的注册方式有哪些,推荐的字体资源存放路径是哪里,如何从资源存放路径中取出字体资源(API 10) 842 843**解决措施** 844 845在工程中存放开发者自定义字体资源文件,代码中通过registerFont接口进行自定义字体注册,便可以在文本组件中使用fontFamily属性使用。 846推荐使用$rawfile方式引用自定义字体资源,资源可放在resources/rawfile目录下。 847 848**参考链接** 849 850[@ohos.font (注册自定义字体)](../reference/apis-arkui/js-apis-font.md) 851 852## Text组件如何加载Unicode字符(API 10) 853 854**解决措施** 855 856在Text组件入参content中使用字符串,在字符串中转义Unicode编码,示例代码如下: 857 858```ts 859@Entry 860@Component 861struct text { 862 build() { 863 Column(){ 864 Text("\u{1F468}\u200D\u{1F468}\u200D\u{1F467}\u200D\u{1F466}") 865 .width(100) 866 .height(100) 867 .fontSize(50) 868 } 869 } 870} 871``` 872 873## 类似js中的slot插槽功能在ArkTS中如何实现(API 10) 874 875**解决措施** 876 877ArkUI还提供了一种更轻量的UI元素复用机制@Builder,@Builder所装饰的函数遵循build()函数语法规则,开发者可以将重复使用的UI元素抽象成一个方法,在build方法里调用; 878另外,ArkUI引入了@BuilderParam装饰器,@BuilderParam用来装饰指向@Builder方法的变量,开发者可在初始化自定义组件时对此属性进行赋值,为自定义组件增加特定的功能。该装饰器用于声明任意UI描述的一个元素,类似slot占位符。 879参考@Builder 和@BuilderParam。 880 881**参考链接** 882 8831. [@Builder装饰器:自定义构建函数](../quick-start/arkts-builder.md) 8842. [@BuilderParam装饰器:引用@Builder函数](../quick-start/arkts-builderparam.md)