1# \@Builder装饰器:自定义构建函数 2 3ArkUI提供了一种轻量的UI元素复用机制\@Builder,其内部UI结构固定,仅与使用方进行数据传递,开发者可以将重复使用的UI元素抽象成一个方法,在build方法里调用。 4 5为了简化语言,我们将\@Builder装饰的函数也称为“自定义构建函数”。 6 7在阅读本文档前,建议提前阅读:[基本语法概述](./arkts-basic-syntax-overview.md),[声明式UI描述](./arkts-declarative-ui-description.md),[自定义组件-创建自定义组件](./arkts-create-custom-components.md)。 8 9> **说明:** 10> 11> 从API version 9开始,该装饰器支持在ArkTS卡片中使用。 12> 13> 从API version 11开始,该装饰器支持在原子化服务中使用。 14 15 16## 装饰器使用说明 17 18\@Builder装饰器有两种使用方式,分别是定义在自定义组件内部的私有自定义构建函数和定义在全局的全局自定义构建函数。 19 20### 私有自定义构建函数 21 22定义的语法: 23 24```ts 25@Entry 26@Component 27struct BuilderDemo { 28 @Builder 29 showTextBuilder() { 30 Text('Hello World') 31 .fontSize(30) 32 .fontWeight(FontWeight.Bold) 33 } 34 @Builder 35 showTextValueBuilder(param: string) { 36 Text(param) 37 .fontSize(30) 38 .fontWeight(FontWeight.Bold) 39 } 40 build() { 41 Column() { 42 // 无参数 43 this.showTextBuilder() 44 // 有参数 45 this.showTextValueBuilder('Hello @Builder') 46 } 47 } 48} 49``` 50 51使用方法: 52 53```ts 54this.showTextBuilder() 55``` 56 57- 允许在自定义组件内定义一个或多个@Builder方法,该方法被认为是该组件的私有、特殊类型的成员函数。 58 59- 私有自定义构建函数允许在自定义组件内、build方法和其他自定义构建函数中调用。 60 61- 在自定义函数体中,this指代当前所属组件,组件的状态变量可以在自定义构建函数内访问。建议通过this访问自定义组件的状态变量而不是参数传递。 62 63 64### 全局自定义构建函数 65 66定义的语法: 67 68```ts 69@Builder 70function showTextBuilder() { 71 Text('Hello World') 72 .fontSize(30) 73 .fontWeight(FontWeight.Bold) 74} 75@Entry 76@Component 77struct BuilderDemo { 78 build() { 79 Column() { 80 showTextBuilder() 81 } 82 } 83} 84``` 85 86使用方法: 87 88```ts 89showTextBuilder() 90``` 91 92- 如果不涉及组件状态变化,建议使用全局的自定义构建方法。 93 94- 全局自定义构建函数允许在build方法和其他自定义构建函数中调用。 95 96 97## 参数传递规则 98 99自定义构建函数的参数传递有[按值传递](#按值传递参数)和[按引用传递](#按引用传递参数)两种,均需遵守以下规则: 100 101- 参数的类型必须与参数声明的类型一致,不允许undefined、null和返回undefined、null的表达式。 102 103- 在@Builder修饰的函数内部,不允许改变参数值。 104 105- \@Builder内UI语法遵循[UI语法规则](arkts-create-custom-components.md#build函数)。 106 107- 只有传入一个参数,且参数需要直接传入对象字面量才会按引用传递该参数,其余传递方式均为按值传递。 108 109### 按值传递参数 110 111调用\@Builder装饰的函数默认按值传递。当传递的参数为状态变量时,状态变量的改变不会引起\@Builder方法内的UI刷新。所以当使用状态变量的时候,推荐使用[按引用传递](#按引用传递参数)。 112 113```ts 114@Builder function overBuilder(paramA1: string) { 115 Row() { 116 Text(`UseStateVarByValue: ${paramA1} `) 117 } 118} 119@Entry 120@Component 121struct Parent { 122 @State label: string = 'Hello'; 123 build() { 124 Column() { 125 overBuilder(this.label) 126 } 127 } 128} 129``` 130 131### 按引用传递参数 132 133按引用传递参数时,传递的参数可为状态变量,且状态变量的改变会引起\@Builder方法内的UI刷新。 134 135```ts 136class Tmp { 137 paramA1: string = ''; 138} 139 140@Builder function overBuilder(params: Tmp) { 141 Row() { 142 Text(`UseStateVarByReference: ${params.paramA1} `) 143 } 144} 145@Entry 146@Component 147struct Parent { 148 @State label: string = 'Hello'; 149 build() { 150 Column() { 151 // 在父组件中调用overBuilder组件时, 152 // 把this.label通过引用传递的方式传给overBuilder组件。 153 overBuilder({ paramA1: this.label }) 154 Button('Click me').onClick(() => { 155 // 单击Click me后,UI文本从Hello更改为ArkUI。 156 this.label = 'ArkUI'; 157 }) 158 } 159 } 160} 161``` 162 163## 限制条件 164 1651. \@Builder装饰的函数内部,不允许修改参数值,否则框架会抛出运行时错误。开发者可以在调用\@Builder的自定义组件里改变其参数。请参考[在@Builder装饰的函数内部修改入参内容](#在builder装饰的函数内部修改入参内容)。 166 1672. \@Builder通过按引用传递的方式传入参数,才会触发动态渲染UI,并且参数只能是一个。请参考[按引用传递参数](#按引用传递参数)。 168 1693. \@Builder如果传入的参数是两个或两个以上,不会触发动态渲染UI。请参考[@Builder存在两个或者两个以上参数](#builder存在两个或者两个以上参数)。 170 1714. \@Builder传入的参数中同时包含按值传递和按引用传递两种方式,不会触发动态渲染UI。请参考[@Builder存在两个或者两个以上参数](#builder存在两个或者两个以上参数)。 172 1735. \@Builder的参数必须按照对象字面量的形式,把所需要的属性一一传入,才会触发动态渲染UI。请参考[@Builder存在两个或者两个以上参数](#builder存在两个或者两个以上参数)。 174 175 176## 使用场景 177 178### 自定义组件内使用自定义构建函数 179 180创建私有的\@Builder方法,在Column里面使用this.builder()方式调用,通过aboutToAppear生命周期函数和按钮的点击事件改变builder_value的内容,实现动态渲染UI。 181 182```ts 183@Entry 184@Component 185struct PrivateBuilder { 186 @State builder_value: string = 'Hello'; 187 188 @Builder builder() { 189 Column(){ 190 Text(this.builder_value) 191 .fontSize(30) 192 .fontWeight(FontWeight.Bold) 193 } 194 } 195 196 aboutToAppear(): void { 197 setTimeout(() => { 198 this.builder_value = 'Hello World'; 199 },3000) 200 } 201 202 build() { 203 Row() { 204 Column() { 205 Text(this.builder_value) 206 .fontSize(30) 207 .fontWeight(FontWeight.Bold) 208 this.builder() 209 Button('点击改变builder_value内容') 210 .onClick(() => { 211 this.builder_value ='builder_value被点击了'; 212 }) 213 } 214 } 215 } 216} 217``` 218 219### 使用全局自定义构建函数 220 221创建全局的\@Builder方法,在Column里面使用overBuilder()方式调用,通过以对象字面量的形式传递参数,无论是简单类型还是复杂类型,值的改变都会引起UI界面的刷新。 222 223```ts 224class ChildTmp { 225 val: number = 1; 226} 227 228class Tmp { 229 str_value: string = 'Hello'; 230 num_value: number = 0; 231 tmp_value: ChildTmp = new ChildTmp(); 232 arrayTmp_value: Array<ChildTmp> = []; 233} 234 235@Builder function overBuilder(param: Tmp) { 236 Column() { 237 Text(`str_value: ${param.str_value}`) 238 Text(`num_value: ${param.num_value}`) 239 Text(`tmp_value: ${param.tmp_value.val}`) 240 ForEach(param.arrayTmp_value, (item: ChildTmp) => { 241 Text(`arrayTmp_value: ${item.val}`) 242 }, (item: ChildTmp) => JSON.stringify(item)) 243 } 244} 245 246@Entry 247@Component 248struct Parent { 249 @State objParam: Tmp = new Tmp(); 250 build() { 251 Column() { 252 Text('通过调用@Builder渲染UI界面') 253 .fontSize(20) 254 overBuilder({str_value: this.objParam.str_value, num_value: this.objParam.num_value, 255 tmp_value: this.objParam.tmp_value, arrayTmp_value: this.objParam.arrayTmp_value}) 256 Line() 257 .width('100%') 258 .height(10) 259 .backgroundColor('#000000').margin(10) 260 Button('点击改变参数值').onClick(() => { 261 this.objParam.str_value = 'Hello World'; 262 this.objParam.num_value = 1; 263 this.objParam.tmp_value.val = 8; 264 const child_value: ChildTmp = { 265 val: 2 266 } 267 this.objParam.arrayTmp_value.push(child_value) 268 }) 269 } 270 } 271} 272``` 273 274### 修改装饰器修饰的变量触发UI刷新 275 276此种场景@Builder只是用来展示Text组件,没有参与动态UI刷新的功能,Text组件中值的变化是使用了装饰器的特性,监听到值的改变触发的UI刷新,而不是通过\@Builder的能力触发的。 277 278```ts 279class Tmp { 280 str_value: string = 'Hello'; 281} 282 283@Entry 284@Component 285struct Parent { 286 @State objParam: Tmp = new Tmp(); 287 @State label: string = 'World'; 288 289 @Builder privateBuilder() { 290 Column() { 291 Text(`wrapBuilder str_value: ${this.objParam.str_value}`) 292 Text(`wrapBuilder num: ${this.label}`) 293 } 294 } 295 296 build() { 297 Column() { 298 Text('通过调用@Builder渲染UI界面') 299 .fontSize(20) 300 this.privateBuilder() 301 Line() 302 .width('100%') 303 .height(10) 304 .backgroundColor('#000000').margin(10) 305 Button('点击改变参数值').onClick(() => { 306 this.objParam.str_value = 'str_value Hello World'; 307 this.label = 'label Hello World' 308 }) 309 } 310 } 311} 312``` 313 314### 使用全局和局部的@Builder传入customBuilder类型 315 316当某个参数类型为customBuilder的时候,可以把定义的\@Builder函数传入,因为customBuilder实际是一个Function(() => any)或者是void类型,而\@Builder实际也是一个Function类型。此场景中通过把\@Builder传入已实现特定的效果。 317 318```ts 319@Builder 320function overBuilder() { 321 Row() { 322 Text('全局 Builder') 323 .fontSize(30) 324 .fontWeight(FontWeight.Bold) 325 } 326} 327 328@Entry 329@Component 330struct customBuilderDemo { 331 @State arr: number[] = [0, 1, 2, 3, 4]; 332 333 @Builder privateBuilder() { 334 Row() { 335 Text('局部 Builder') 336 .fontSize(30) 337 .fontWeight(FontWeight.Bold) 338 } 339 } 340 341 build() { 342 Column() { 343 List({ space: 10 }) { 344 ForEach(this.arr, (item: number) => { 345 ListItem(){ 346 Text(`${item}`) 347 .width('100%') 348 .height(100) 349 .fontSize(16) 350 .textAlign(TextAlign.Center) 351 .borderRadius(10) 352 .backgroundColor(0xFFFFFF) 353 } 354 .swipeAction({ 355 start: { 356 builder: overBuilder() 357 }, 358 end: { 359 builder: () => { this.privateBuilder() } 360 } 361 }) 362 }, (item: string) => JSON.stringify(item)) 363 } 364 } 365 } 366} 367``` 368 369### 多层\@Builder方法嵌套使用 370 371在\@Builder方法内调用自定义组件或者其他\@Builder方法,以实现多个\@Builder嵌套使用的场景,要想实现最里面的\@Builder动态UI刷新功能,必须要保证每层调用\@Builder的地方使用按引用传递的方式。这里的[\$$](./arkts-two-way-sync.md)也可以换成其他名称,[\$$](./arkts-two-way-sync.md)不是必须的参数形式。 372 373```ts 374class Tmp { 375 paramA1: string = ''; 376} 377 378@Builder function parentBuilder($$: Tmp) { 379 Row() { 380 Column() { 381 Text(`parentBuilder===${$$.paramA1}`) 382 .fontSize(30) 383 .fontWeight(FontWeight.Bold) 384 HelloComponent({message: $$.paramA1}) 385 childBuilder({paramA1: $$.paramA1}) 386 } 387 } 388} 389 390@Component 391struct HelloComponent { 392 @Prop message: string = ''; 393 394 build() { 395 Row() { 396 Text(`HelloComponent===${this.message}`) 397 .fontSize(30) 398 .fontWeight(FontWeight.Bold) 399 } 400 } 401} 402 403@Builder 404function childBuilder($$: Tmp) { 405 Row() { 406 Column() { 407 Text(`childBuilder===${$$.paramA1}`) 408 .fontSize(30) 409 .fontWeight(FontWeight.Bold) 410 HelloChildComponent({message: $$.paramA1}) 411 grandsonBuilder({paramA1: $$.paramA1}) 412 } 413 } 414} 415 416@Component 417struct HelloChildComponent { 418 @Prop message: string = ''; 419 build() { 420 Row() { 421 Text(`HelloChildComponent===${this.message}`) 422 .fontSize(30) 423 .fontWeight(FontWeight.Bold) 424 } 425 } 426} 427 428@Builder function grandsonBuilder($$: Tmp) { 429 Row() { 430 Column() { 431 Text(`grandsonBuilder===${$$.paramA1}`) 432 .fontSize(30) 433 .fontWeight(FontWeight.Bold) 434 HelloGrandsonComponent({message: $$.paramA1}) 435 } 436 } 437} 438 439@Component 440struct HelloGrandsonComponent { 441 @Prop message: string; 442 build() { 443 Row() { 444 Text(`HelloGrandsonComponent===${this.message}`) 445 .fontSize(30) 446 .fontWeight(FontWeight.Bold) 447 } 448 } 449} 450 451@Entry 452@Component 453struct Parent { 454 @State label: string = 'Hello'; 455 build() { 456 Column() { 457 parentBuilder({paramA1: this.label}) 458 Button('Click me').onClick(() => { 459 this.label = 'ArkUI'; 460 }) 461 } 462 } 463} 464``` 465 466### \@Builder函数联合V2装饰器使用 467 468使用全局@Builder和局部@Builder在@ComponentV2修饰的自定义组件中调用,配合@ObservedV2和@Trace装饰器来监听具体值的变化,以达到触发UI刷新的功能。 469 470```ts 471@ObservedV2 472class Info { 473 @Trace name: string = ''; 474 @Trace age: number = 0; 475} 476 477@Builder 478function overBuilder(param: Info) { 479 Column() { 480 Text(`全局@Builder name :${param.name}`) 481 .fontSize(30) 482 .fontWeight(FontWeight.Bold) 483 Text(`全局@Builder age :${param.age}`) 484 .fontSize(30) 485 .fontWeight(FontWeight.Bold) 486 } 487} 488 489@ComponentV2 490struct ChildPage { 491 @Require @Param childInfo: Info; 492 build() { 493 overBuilder({name: this.childInfo.name, age: this.childInfo.age}) 494 } 495} 496 497@Entry 498@ComponentV2 499struct ParentPage { 500 info1: Info = { name: "Tom", age: 25 }; 501 @Local info2: Info = { name: "Tom", age: 25 }; 502 503 @Builder 504 privateBuilder() { 505 Column() { 506 Text(`局部@Builder name :${this.info1.name}`) 507 .fontSize(30) 508 .fontWeight(FontWeight.Bold) 509 Text(`局部@Builder age :${this.info1.age}`) 510 .fontSize(30) 511 .fontWeight(FontWeight.Bold) 512 } 513 } 514 515 build() { 516 Column() { 517 Text(`info1: ${this.info1.name} ${this.info1.age}`) // Text1 518 .fontSize(30) 519 .fontWeight(FontWeight.Bold) 520 this.privateBuilder() // 调用局部@Builder 521 Line() 522 .width('100%') 523 .height(10) 524 .backgroundColor('#000000').margin(10) 525 Text(`info2: ${this.info2.name} ${this.info2.age}`) // Text2 526 .fontSize(30) 527 .fontWeight(FontWeight.Bold) 528 overBuilder({ name: this.info2.name, age: this.info2.age}) // 调用全局@Builder 529 Line() 530 .width('100%') 531 .height(10) 532 .backgroundColor('#000000').margin(10) 533 Text(`info1: ${this.info1.name} ${this.info1.age}`) // Text1 534 .fontSize(30) 535 .fontWeight(FontWeight.Bold) 536 ChildPage({ childInfo: this.info1}) // 调用自定义组件 537 Line() 538 .width('100%') 539 .height(10) 540 .backgroundColor('#000000').margin(10) 541 Text(`info2: ${this.info2.name} ${this.info2.age}`) // Text2 542 .fontSize(30) 543 .fontWeight(FontWeight.Bold) 544 ChildPage({ childInfo: this.info2}) // 调用自定义组件 545 Line() 546 .width('100%') 547 .height(10) 548 .backgroundColor('#000000').margin(10) 549 Button("change info1&info2") 550 .onClick(() => { 551 this.info1 = { name: "Cat", age: 18}; // Text1不会刷新,原因是没有装饰器修饰监听不到值的改变。 552 this.info2 = { name: "Cat", age: 18}; // Text2会刷新,原因是有装饰器修饰,可以监听到值的改变。 553 }) 554 } 555 } 556} 557``` 558 559## 常见问题 560 561### \@Builder存在两个或者两个以上参数 562 563当参数存在两个或者两个以上的时候,就算通过对象字面量的形式传递,值的改变也不会引起UI刷新。 564 565【反例】 566 567```ts 568class GlobalTmp { 569 str_value: string = 'Hello'; 570} 571 572@Builder function overBuilder(param: GlobalTmp, num: number) { 573 Column() { 574 Text(`str_value: ${param.str_value}`) 575 Text(`num: ${num}`) 576 } 577} 578 579@Entry 580@Component 581struct Parent { 582 @State objParam: GlobalTmp = new GlobalTmp(); 583 @State num: number = 0; 584 build() { 585 Column() { 586 Text('通过调用@Builder渲染UI界面') 587 .fontSize(20) 588 // 使用了两个参数,用法错误。 589 overBuilder({str_value: this.objParam.str_value}, this.num) 590 Line() 591 .width('100%') 592 .height(10) 593 .backgroundColor('#000000').margin(10) 594 Button('点击改变参数值').onClick(() => { 595 this.objParam.str_value = 'Hello World'; 596 this.num = 1; 597 }) 598 } 599 } 600} 601``` 602 603【反例】 604 605```ts 606class GlobalTmp { 607 str_value: string = 'Hello'; 608} 609class SecondTmp { 610 num_value: number = 0; 611} 612@Builder function overBuilder(param: GlobalTmp, num: SecondTmp) { 613 Column() { 614 Text(`str_value: ${param.str_value}`) 615 Text(`num: ${num.num_value}`) 616 } 617} 618 619@Entry 620@Component 621struct Parent { 622 @State strParam: GlobalTmp = new GlobalTmp(); 623 @State numParam: SecondTmp = new SecondTmp(); 624 build() { 625 Column() { 626 Text('通过调用@Builder渲染UI界面') 627 .fontSize(20) 628 // 使用了两个参数,用法错误。 629 overBuilder({str_value: this.strParam.str_value}, {num_value: this.numParam.num_value}) 630 Line() 631 .width('100%') 632 .height(10) 633 .backgroundColor('#000000').margin(10) 634 Button('点击改变参数值').onClick(() => { 635 this.strParam.str_value = 'Hello World'; 636 this.numParam.num_value = 1; 637 }) 638 } 639 } 640} 641``` 642 643\@Builder只接受一个参数,当传入一个参数的时候,通过对象字面量的形式传递,值的改变会引起UI的刷新。 644 645【正例】 646 647```ts 648class GlobalTmp { 649 str_value: string = 'Hello'; 650 num_value: number = 0; 651} 652@Builder function overBuilder(param: GlobalTmp) { 653 Column() { 654 Text(`str_value: ${param.str_value}`) 655 Text(`num: ${param.num_value}`) 656 } 657} 658 659@Entry 660@Component 661struct Parent { 662 @State objParam: GlobalTmp = new GlobalTmp(); 663 build() { 664 Column() { 665 Text('通过调用@Builder渲染UI界面') 666 .fontSize(20) 667 overBuilder({str_value: this.objParam.str_value, num_value: this.objParam.num_value}) 668 Line() 669 .width('100%') 670 .height(10) 671 .backgroundColor('#000000').margin(10) 672 Button('点击改变参数值').onClick(() => { 673 this.objParam.str_value = 'Hello World'; 674 this.objParam.num_value = 1; 675 }) 676 } 677 } 678} 679``` 680 681### 使用@ComponentV2装饰器触发动态刷新 682 683使用按值传递的方式,在@ComponentV2装饰器修饰的自定义组件里配合使用@ObservedV2和@Trace装饰器可以实现刷新UI功能。 684 685【反例】 686 687在@ComponentV2装饰的自定义组件中,使用简单数据类型不可以触发UI的刷新。 688 689```ts 690@ObservedV2 691class ParamTmp { 692 @Trace count : number = 0; 693} 694 695@Builder 696function renderNumber(paramNum: number) { 697 Text(`paramNum : ${paramNum}`) 698 .fontSize(30) 699 .fontWeight(FontWeight.Bold) 700} 701 702@Entry 703@ComponentV2 704struct PageBuilder { 705 @Local class_value: ParamTmp = new ParamTmp(); 706 // 此处使用简单数据类型不支持刷新UI的能力。 707 @Local num_value: number = 0; 708 private progressTimer: number = -1; 709 710 aboutToAppear(): void { 711 this.progressTimer = setInterval(() => { 712 if (this.class_value.count < 100) { 713 this.class_value.count += 5; 714 this.num_value += 5; 715 } else { 716 clearInterval(this.progressTimer); 717 } 718 }, 500); 719 } 720 721 build() { 722 Column() { 723 renderNumber(this.num_value) 724 } 725 .width('100%') 726 .height('100%') 727 .padding(50) 728 } 729} 730``` 731 732【正例】 733 734在@ComponentV2装饰中,只有使用@ObservedV2修饰的ParamTmp类和@Trace修饰的count属性才可以触发UI的刷新。 735 736```ts 737@ObservedV2 738class ParamTmp { 739 @Trace count : number = 0; 740} 741 742@Builder 743function renderText(param: ParamTmp) { 744 Column() { 745 Text(`param : ${param.count}`) 746 .fontSize(20) 747 .fontWeight(FontWeight.Bold) 748 } 749} 750 751@Builder 752function renderMap(paramMap: Map<string,number>) { 753 Text(`paramMap : ${paramMap.get('name')}`) 754 .fontSize(20) 755 .fontWeight(FontWeight.Bold) 756} 757 758@Builder 759function renderSet(paramSet: Set<number>) { 760 Text(`paramSet : ${paramSet.size}`) 761 .fontSize(20) 762 .fontWeight(FontWeight.Bold) 763} 764 765@Builder 766function renderNumberArr(paramNumArr: number[]) { 767 Text(`paramNumArr : ${paramNumArr[0]}`) 768 .fontSize(20) 769 .fontWeight(FontWeight.Bold) 770} 771 772@Entry 773@ComponentV2 774struct PageBuilder { 775 @Local builderParams: ParamTmp = new ParamTmp(); 776 @Local map_value: Map<string,number> = new Map(); 777 @Local set_value: Set<number> = new Set([0]); 778 @Local numArr_value: number[] = [0]; 779 private progressTimer: number = -1; 780 781 aboutToAppear(): void { 782 this.progressTimer = setInterval(() => { 783 if (this.builderParams.count < 100) { 784 this.builderParams.count += 5; 785 this.map_value.set('name', this.builderParams.count); 786 this.set_value.add(this.builderParams.count); 787 this.numArr_value[0] = this.builderParams.count; 788 } else { 789 clearInterval(this.progressTimer); 790 } 791 }, 500); 792 } 793 794 @Builder 795 localBuilder() { 796 Column() { 797 Text(`localBuilder : ${this.builderParams.count}`) 798 .fontSize(20) 799 .fontWeight(FontWeight.Bold) 800 } 801 } 802 803 build() { 804 Column() { 805 this.localBuilder() 806 Text(`builderParams :${this.builderParams.count}`) 807 .fontSize(20) 808 .fontWeight(FontWeight.Bold) 809 renderText(this.builderParams) 810 renderText({ count: this.builderParams.count }) 811 renderMap(this.map_value) 812 renderSet(this.set_value) 813 renderNumberArr(this.numArr_value) 814 } 815 .width('100%') 816 .height('100%') 817 } 818} 819``` 820 821### 在\@Builder装饰的函数内部修改入参内容 822 823【反例】 824 825```ts 826interface Temp { 827 paramA: string; 828} 829 830@Builder function overBuilder(param: Temp) { 831 Row() { 832 Column() { 833 Button(`overBuilder === ${param.paramA}`) 834 .onClick(() => { 835 // 错误写法,不允许在@Builder装饰的函数内部修改参数值 836 param.paramA = 'Yes'; 837 }) 838 } 839 } 840} 841 842@Entry 843@Component 844struct Parent { 845 @State label: string = 'Hello'; 846 847 build() { 848 Column() { 849 overBuilder({paramA: this.label}) 850 Button('click me') 851 .onClick(() => { 852 this.label = 'ArkUI'; 853 }) 854 } 855 } 856} 857``` 858 859【正例】 860 861```ts 862interface Temp { 863 paramA: string; 864} 865 866@Builder function overBuilder(param: Temp) { 867 Row() { 868 Column() { 869 Button(`overBuilder === ${param.paramA}`) 870 } 871 } 872} 873 874@Entry 875@Component 876struct Parent { 877 @State label: string = 'Hello'; 878 879 build() { 880 Column() { 881 overBuilder({paramA: this.label}) 882 Button('click me') 883 .onClick(() => { 884 this.label = 'ArkUI'; 885 }) 886 } 887 } 888} 889```