• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# \@BuilderParam装饰器:引用\@Builder函数
2<!--Kit: ArkUI-->
3<!--Subsystem: ArkUI-->
4<!--Owner: @zhangboren-->
5<!--Designer: @zhangboren-->
6<!--Tester: @TerryTsao-->
7<!--Adviser: @zhang_yixin13-->
8
9当开发者创建自定义组件并需要为其添加特定功能(例如:点击跳转操作)时,如果直接在组件内嵌入事件方法,会导致所有该自定义组件的实例都增加此功能。为了解决组件功能定制化的问题,ArkUI引入了@BuilderParam装饰器。@BuilderParam用于装饰指向@Builder方法的变量,开发者可以在初始化自定义组件时,使用不同的方式(例如:参数修改、尾随闭包、借用箭头函数等)对@BuilderParam装饰的自定义构建函数进行传参赋值。在自定义组件内部,通过调用@BuilderParam为组件增加特定功能。该装饰器用于声明任意UI描述的元素,类似于slot占位符。
10
11在阅读本文档前,建议提前阅读:[\@Builder](./arkts-builder.md)。
12
13> **说明:**
14>
15> 从API version 9开始,该装饰器支持在ArkTS卡片中使用。
16>
17> 从API version 11开始,该装饰器支持在原子化服务中使用。
18
19
20## 装饰器使用说明
21
22
23### 初始化\@BuilderParam装饰的方法
24
25\@BuilderParam装饰的方法只能被自定义构建函数(\@Builder装饰的方法)初始化。
26
27- 使用所属自定义组件的自定义构建函数或者全局的自定义构建函数,在本地初始化\@BuilderParam。
28
29  ```ts
30  @Builder
31  function overBuilder() {
32  }
33
34  @Component
35  struct Child {
36    @Builder
37    doNothingBuilder() {
38    }
39
40    // 使用自定义组件的自定义构建函数初始化@BuilderParam
41    @BuilderParam customBuilderParam: () => void = this.doNothingBuilder;
42    // 使用全局自定义构建函数初始化@BuilderParam
43    @BuilderParam customOverBuilderParam: () => void = overBuilder;
44
45    build() {
46    }
47  }
48  ```
49
50- 用父组件自定义构建函数初始化子组件\@BuilderParam装饰的方法。
51
52  ```ts
53  @Component
54  struct Child {
55    @Builder
56    customBuilder() {
57    }
58
59    @BuilderParam customBuilderParam: () => void = this.customBuilder;
60
61    build() {
62      Column() {
63        this.customBuilderParam()
64      }
65    }
66  }
67
68  @Entry
69  @Component
70  struct Parent {
71    @Builder
72    componentBuilder() {
73      Text(`Parent builder `)
74    }
75
76    build() {
77      Column() {
78        Child({ customBuilderParam: this.componentBuilder })
79      }
80    }
81  }
82  ```
83  **图1** 示例效果图
84
85  ![builderparam-demo1](figures/builderparam-demo1.png)
86
87
88- 需要注意this的指向。
89
90  this指向示例如下:
91
92    ```ts
93    @Component
94    struct Child {
95      label: string = 'Child';
96
97      @Builder
98      customBuilder() {
99      }
100
101      @Builder
102      customChangeThisBuilder() {
103      }
104
105      @BuilderParam customBuilderParam: () => void = this.customBuilder;
106      @BuilderParam customChangeThisBuilderParam: () => void = this.customChangeThisBuilder;
107
108      build() {
109        Column() {
110          this.customBuilderParam()
111          this.customChangeThisBuilderParam()
112        }
113      }
114    }
115
116    @Entry
117    @Component
118    struct Parent {
119      label: string = 'Parent';
120
121      @Builder
122      componentBuilder() {
123        Text(`${this.label}`)
124      }
125
126      build() {
127        Column() {
128          // 调用this.componentBuilder()时,this指向当前@Entry所装饰的Parent组件,即label变量的值为'Parent'。
129          this.componentBuilder()
130          Child({
131            // 把this.componentBuilder传给子组件Child的@BuilderParam customBuilderParam,this指向的是子组件Child,即label变量的值为'Child'。
132            customBuilderParam: this.componentBuilder,
133            // 把():void=>{this.componentBuilder()}传给子组件Child的@BuilderParam customChangeThisBuilderParam,
134            // 因为箭头函数的this指向的是宿主对象,所以label变量的值为'Parent'。
135            customChangeThisBuilderParam: (): void => {
136              this.componentBuilder()
137            }
138          })
139        }
140      }
141    }
142    ```
143  **图2** 示例效果图
144
145  ![builderparam-demo2](figures/builderparam-demo2.png)
146
147
148## 限制条件
149
150- 使用`@BuilderParam`装饰的变量只能通过`@Builder`函数进行初始化。具体参见[@BuilderParam装饰器初始化的值必须为@Builder](#builderparam装饰器初始化的值必须为builder)。
151
152- 当@Require装饰器和@BuilderParam装饰器一起使用时,@BuilderParam装饰器必须进行初始化。具体请参见[@Require装饰器和@BuilderParam装饰器联合使用](#require装饰器和builderparam装饰器联合使用)。
153
154- 在自定义组件尾随闭包的场景下,子组件有且仅有一个\@BuilderParam用来接收此尾随闭包,且此\@BuilderParam装饰的方法不能有参数。详情见[尾随闭包初始化组件](#尾随闭包初始化组件)。
155
156## 使用场景
157
158### 参数初始化组件
159
160`@BuilderParam`装饰的方法为有参数或无参数两种形式,需与指向的`@Builder`方法类型匹配。
161
162```ts
163class Tmp {
164  label: string = '';
165}
166
167@Builder
168function overBuilder($$: Tmp) {
169  Text($$.label)
170    .width(400)
171    .height(50)
172    .backgroundColor(Color.Green)
173}
174
175@Component
176struct Child {
177  label: string = 'Child';
178
179  @Builder
180  customBuilder() {
181  }
182
183  // 无参数类型,指向的customBuilder也是无参数类型
184  @BuilderParam customBuilderParam: () => void = this.customBuilder;
185  // 有参数类型,指向的overBuilder也是有参数类型的方法
186  @BuilderParam customOverBuilderParam: ($$: Tmp) => void = overBuilder;
187
188  build() {
189    Column() {
190      this.customBuilderParam()
191      this.customOverBuilderParam({ label: 'global Builder label' })
192    }
193  }
194}
195
196@Entry
197@Component
198struct Parent {
199  label: string = 'Parent';
200
201  @Builder
202  componentBuilder() {
203    Text(`${this.label}`)
204  }
205
206  build() {
207    Column() {
208      this.componentBuilder()
209      Child({ customBuilderParam: this.componentBuilder, customOverBuilderParam: overBuilder })
210    }
211  }
212}
213```
214**图3** 示例效果图
215
216![builderparam-demo3](figures/builderparam-demo3.png)
217
218
219### 尾随闭包初始化组件
220
221在自定义组件中,使用\@BuilderParam装饰的属性可通过尾随闭包进行初始化。初始化时,组件后需紧跟一个大括号“{}”形成尾随闭包场景。
222
223> **说明:**
224>
225>  - 此场景下自定义组件内仅有一个使用\@BuilderParam装饰的属性。
226>
227>  - 此场景下自定义组件不支持通用属性。
228
229开发者可以将尾随闭包内的内容看作\@Builder装饰的函数传给\@BuilderParam。
230
231示例1:
232
233```ts
234@Component
235struct CustomContainer {
236  @Prop header: string = '';
237
238  @Builder
239  closerBuilder() {
240  }
241
242  // 使用父组件的尾随闭包{}(@Builder装饰的方法)初始化子组件@BuilderParam
243  @BuilderParam closer: () => void = this.closerBuilder;
244
245  build() {
246    Column() {
247      Text(this.header)
248        .fontSize(30)
249      this.closer()
250    }
251  }
252}
253
254@Builder
255function specificParam(label1: string, label2: string) {
256  Column() {
257    Text(label1)
258      .fontSize(30)
259    Text(label2)
260      .fontSize(30)
261  }
262}
263
264@Entry
265@Component
266struct CustomContainerUser {
267  @State text: string = 'header';
268
269  build() {
270    Column() {
271      // 创建CustomContainer,在创建CustomContainer时,通过其后紧跟一个大括号“{}”形成尾随闭包
272      // 作为传递给子组件CustomContainer @BuilderParam closer: () => void的参数
273      CustomContainer({ header: this.text }) {
274        Column() {
275          specificParam('testA', 'testB')
276        }.backgroundColor(Color.Yellow)
277        .onClick(() => {
278          this.text = 'changeHeader';
279        })
280      }
281    }
282  }
283}
284```
285**图4** 示例效果图
286
287![builderparam-demo4](figures/builderparam-demo4.png)
288
289使用全局`@Builder`和局部`@Builder`通过尾随闭包的形式对`@ComponentV2`装饰的自定义组件中的`@BuilderParam`进行初始化。
290
291示例2:
292
293```ts
294@ComponentV2
295struct ChildPage {
296  @Require @Param message: string = '';
297
298  @Builder
299  customBuilder() {
300  }
301
302  @BuilderParam customBuilderParam: () => void = this.customBuilder;
303
304  build() {
305    Column() {
306      Text(this.message)
307        .fontSize(30)
308        .fontWeight(FontWeight.Bold)
309      this.customBuilderParam()
310    }
311  }
312}
313
314const builder_value: string = 'Hello World';
315
316@Builder
317function overBuilder() {
318  Row() {
319    Text(`全局 Builder: ${builder_value}`)
320      .fontSize(20)
321      .fontWeight(FontWeight.Bold)
322  }
323}
324
325@Entry
326@ComponentV2
327struct ParentPage {
328  @Local label: string = 'Parent Page';
329
330  @Builder
331  componentBuilder() {
332    Row() {
333      Text(`局部 Builder :${this.label}`)
334        .fontSize(20)
335        .fontWeight(FontWeight.Bold)
336    }
337  }
338
339  build() {
340    Column() {
341      ChildPage({ message: this.label }) {
342        Column() { // 使用局部@Builder,通过组件后紧跟一个大括号“{}”形成尾随闭包去初始化自定义组件@BuilderParam
343          this.componentBuilder();
344        }
345      }
346
347      Line()
348        .width('100%')
349        .height(10)
350        .backgroundColor('#000000').margin(10)
351      ChildPage({ message: this.label }) { // 使用全局@Builder,通过组件后紧跟一个大括号“{}”形成尾随闭包去初始化自定义组件@BuilderParam
352        Column() {
353          overBuilder();
354        }
355      }
356    }
357  }
358}
359```
360
361### 使用\@BuilderParam隔离多组件对\@Builder跳转逻辑的调用
362
363当@Builder封装的系统组件包含跳转逻辑时,所有调用该@Builder的自定义组件将具备该跳转功能。对于需要禁用跳转的特定组件,可使用@BuilderParam来隔离跳转逻辑。
364
365> **说明:**
366>
367> 当前示例代码中使用了Navigation组件导航,具体实现逻辑可以查询[Navigation](../arkts-navigation-navigation.md)指南。
368
369```ts
370import { HelloWorldPageBuilder } from './helloworld';
371
372class navigationParams {
373  pathStack: NavPathStack = new NavPathStack();
374  boo: boolean = true;
375}
376
377@Builder
378function navigationAction(params: navigationParams) {
379  Column() {
380    Navigation(params.pathStack) {
381      Button('router to page', { stateEffect: true, type: ButtonType.Capsule })
382        .width('80%')
383        .height(40)
384        .margin(20)
385        .onClick(() => {
386          // 通过修改@BuilderParam参数决定是否跳转。
387          if (params.boo) {
388            params.pathStack.pushPath({ name: 'HelloWorldPage' });
389          } else {
390            console.info('@BuilderParam setting does not jump');
391          }
392        })
393    }
394    .navDestination(HelloWorldPageBuilder)
395    .hideTitleBar(true)
396    .height('100%')
397    .width('100%')
398  }
399  .height('25%')
400  .width('100%')
401}
402
403@Entry
404@Component
405struct ParentPage {
406  @State info: navigationParams = new navigationParams();
407
408  build() {
409    Column() {
410      Text('ParentPage')
411      navigationAction({ pathStack: this.info.pathStack, boo: true })
412      ChildPageOne()
413      ChildPage_BuilderParam({ eventBuilder: navigationAction })
414    }
415    .height('100%')
416    .width('100%')
417  }
418}
419
420@Component
421struct ChildPageOne {
422  @State info: navigationParams = new navigationParams();
423
424  build() {
425    Column() {
426      Text('ChildPage')
427      navigationAction({ pathStack: this.info.pathStack, boo: true })
428    }
429  }
430}
431
432@Component
433struct ChildPage_BuilderParam {
434  @State info: navigationParams = new navigationParams();
435  @BuilderParam eventBuilder: (param: navigationParams) => void = navigationAction;
436
437  build() {
438    Column() {
439      Text('ChildPage_BuilderParam')
440      // 对传递过来的全局@Builder进行参数修改,可以实现禁用点击跳转的功能。
441      this.eventBuilder({ pathStack: this.info.pathStack, boo: false })
442    }
443  }
444}
445```
446
447```ts
448// helloworld.ets
449@Builder
450export function HelloWorldPageBuilder() {
451  HelloWorldPage()
452}
453
454@Component
455struct HelloWorldPage {
456  @State message: string = 'Hello World';
457  @State pathStack: NavPathStack = new NavPathStack();
458
459  build() {
460    NavDestination() {
461      Column() {
462        Text(this.message)
463          .fontSize(20)
464          .fontWeight(FontWeight.Bold)
465      }
466    }
467    .height('100%')
468    .width('100%')
469  }
470}
471```
472
473```ts
474// router_map.json
475{
476  "routerMap": [
477    {
478      "name": "HelloWorldPage",
479      "buildFunction": "HelloWorldPageBuilder",
480      "pageSourceFile": "src/main/ets/pages/helloworld.ets"
481    }
482  ]
483}
484```
485
486```ts
487// module.json5
488{
489  "module": {
490    "routerMap": "$profile:router_map",
491    ......
492  }
493}
494```
495
496**图5** 示例效果图
497
498![builderparam-demo7](figures/builderparam-demo7.gif)
499
500### 使用全局和局部\@Builder初始化\@BuilderParam
501
502在自定义组件中,使用\@BuilderParam装饰的变量接收父组件通过\@Builder传递的内容进行初始化,由于父组件的\@Builder可以使用箭头函数改变当前的this指向,因此使用\@BuilderParam装饰的变量会展示不同的内容。
503
504```ts
505@Component
506struct ChildPage {
507  label: string = 'Child Page';
508
509  @Builder
510  customBuilder() {
511  }
512
513  @BuilderParam customBuilderParam: () => void = this.customBuilder;
514  @BuilderParam customChangeThisBuilderParam: () => void = this.customBuilder;
515
516  build() {
517    Column() {
518      this.customBuilderParam()
519      this.customChangeThisBuilderParam()
520    }
521  }
522}
523
524const builder_value: string = 'Hello World';
525
526@Builder
527function overBuilder() {
528  Row() {
529    Text(`全局 Builder: ${builder_value}`)
530      .fontSize(20)
531      .fontWeight(FontWeight.Bold)
532  }
533}
534
535@Entry
536@Component
537struct ParentPage {
538  label: string = 'Parent Page';
539
540  @Builder
541  componentBuilder() {
542    Row() {
543      Text(`局部 Builder :${this.label}`)
544        .fontSize(20)
545        .fontWeight(FontWeight.Bold)
546    }
547  }
548
549  build() {
550    Column() {
551      // 调用this.componentBuilder()时,this指向当前@Entry所装饰的ParentPage组件,所以label变量的值为'Parent Page'。
552      this.componentBuilder()
553      ChildPage({
554        // 把this.componentBuilder传给子组件ChildPage的@BuilderParam customBuilderParam,this指向的是子组件ChildPage,所以label变量的值为'Child Page'。
555        customBuilderParam: this.componentBuilder,
556        // 把():void=>{this.componentBuilder()}传给子组件ChildPage的@BuilderParam customChangeThisBuilderParam,
557        // 因为箭头函数的this指向的是宿主对象,所以label变量的值为'Parent Page'。
558        customChangeThisBuilderParam: (): void => {
559          this.componentBuilder()
560        }
561      })
562      Line()
563        .width('100%')
564        .height(10)
565        .backgroundColor('#000000').margin(10)
566      // 调用全局overBuilder()时,this指向当前整个活动页,所以展示的内容为'Hello World'。
567      overBuilder()
568      ChildPage({
569        // 把全局overBuilder传给子组件ChildPage的@BuilderParam customBuilderParam,this指向当前整个活动页,所以展示的内容为'Hello World'。
570        customBuilderParam: overBuilder,
571        // 把全局overBuilder传给子组件ChildPage的@BuilderParam customChangeThisBuilderParam,this指向当前整个活动页,所以展示的内容为'Hello World'。
572        customChangeThisBuilderParam: overBuilder
573      })
574    }
575  }
576}
577```
578**图6** 示例效果图
579
580![builderparam-demo5](figures/builderparam-demo5.png)
581
582### 在@ComponentV2装饰的自定义组件中使用@BuilderParam
583
584使用全局@Builder和局部@Builder初始化@ComponentV2装饰的自定义组件中的@BuilderParam属性。
585
586```ts
587@ComponentV2
588struct ChildPage {
589  @Param label: string = 'Child Page';
590
591  @Builder
592  customBuilder() {
593  }
594
595  @BuilderParam customBuilderParam: () => void = this.customBuilder;
596  @BuilderParam customChangeThisBuilderParam: () => void = this.customBuilder;
597
598  build() {
599    Column() {
600      this.customBuilderParam()
601      this.customChangeThisBuilderParam()
602    }
603  }
604}
605
606const builder_value: string = 'Hello World';
607
608@Builder
609function overBuilder() {
610  Row() {
611    Text(`全局 Builder: ${builder_value}`)
612      .fontSize(20)
613      .fontWeight(FontWeight.Bold)
614  }
615}
616
617@Entry
618@ComponentV2
619struct ParentPage {
620  @Local label: string = 'Parent Page';
621
622  @Builder
623  componentBuilder() {
624    Row() {
625      Text(`局部 Builder :${this.label}`)
626        .fontSize(20)
627        .fontWeight(FontWeight.Bold)
628    }
629  }
630
631  build() {
632    Column() {
633      // 调用this.componentBuilder()时,this指向当前@Entry所装饰的ParentPage组件,所以label变量的值为'Parent Page'。
634      this.componentBuilder()
635      ChildPage({
636        // 把this.componentBuilder传给子组件ChildPage的@BuilderParam customBuilderParam,this指向的是子组件ChildPage,所以label变量的值为'Child Page'。
637        customBuilderParam: this.componentBuilder,
638        // 把():void=>{this.componentBuilder()}传给子组件ChildPage的@BuilderParam customChangeThisBuilderPara
639        // 因为箭头函数的this指向的是宿主对象,所以label变量的值为'Parent Page'。
640        customChangeThisBuilderParam: (): void => {
641          this.componentBuilder()
642        }
643      })
644      Line()
645        .width('100%')
646        .height(5)
647        .backgroundColor('#000000').margin(10)
648      // 调用全局overBuilder()时,this指向当前整个活动页,所以展示的内容为'Hello World'。
649      overBuilder()
650      ChildPage({
651        // 把全局overBuilder传给子组件ChildPage的@BuilderParam customBuilderParam,this指向当前整个活动页,所以展示的内容为'Hello World'。
652        customBuilderParam: overBuilder,
653        // 把全局overBuilder传给子组件ChildPage的@BuilderParam customChangeThisBuilderParam,this指向当前整个活动页,所以展示的内容为'Hello World'。
654        customChangeThisBuilderParam: overBuilder
655      })
656    }
657  }
658}
659```
660**图7** 示例效果图
661
662![builderparam-demo6](figures/builderparam-demo6.png)
663
664
665## 常见问题
666
667### 改变内容UI不刷新
668
669调用自定义组件ChildPage时,通过`this.componentBuilder`形式传递`@Builder`参数。由于`this`指向自定义组件内部,因此在父组件中改变`label`的值时,自定义组件ChildPage无法感知到这一变化。
670
671【反例】
672
673```ts
674@Component
675struct ChildPage {
676  @State label: string = 'Child Page';
677
678  @Builder
679  customBuilder() {
680  }
681
682  @BuilderParam customChangeThisBuilderParam: () => void = this.customBuilder;
683
684  build() {
685    Column() {
686      this.customChangeThisBuilderParam()
687    }
688  }
689}
690
691@Entry
692@Component
693struct ParentPage {
694  @State label: string = 'Parent Page';
695
696  @Builder
697  componentBuilder() {
698    Row() {
699      Text(`Builder :${this.label}`)
700        .fontSize(20)
701        .fontWeight(FontWeight.Bold)
702    }
703  }
704
705  build() {
706    Column() {
707      ChildPage({
708        // 当前写法this指向ChildPage组件内
709        customChangeThisBuilderParam: this.componentBuilder
710      })
711      Button('点击改变label内容')
712        .onClick(() => {
713          this.label = 'Hello World';
714        })
715    }
716  }
717}
718```
719
720使用箭头函数将`@Builder`传递到自定义组件`ChildPage`中,这样`this`指向会停留在父组件`ParentPage`里。因此,在父组件中改变`label`的值时,`ChildPage`会感知到并重新渲染UI。
721
722【正例】
723
724```ts
725@Component
726struct ChildPage {
727  @State label: string = 'Child Page';
728
729  @Builder
730  customBuilder() {
731  }
732
733  @BuilderParam customChangeThisBuilderParam: () => void = this.customBuilder;
734
735  build() {
736    Column() {
737      this.customChangeThisBuilderParam()
738    }
739  }
740}
741
742@Entry
743@Component
744struct ParentPage {
745  @State label: string = 'Parent Page';
746
747  @Builder
748  componentBuilder() {
749    Row() {
750      Text(`Builder :${this.label}`)
751        .fontSize(20)
752        .fontWeight(FontWeight.Bold)
753    }
754  }
755
756  build() {
757    Column() {
758      ChildPage({
759        customChangeThisBuilderParam: () => {
760          this.componentBuilder()
761        }
762      })
763      Button('点击改变label内容')
764        .onClick(() => {
765          this.label = 'Hello World';
766        })
767    }
768  }
769}
770```
771
772### @Require装饰器和@BuilderParam装饰器联合使用
773
774由于@Require装饰器所装饰的变量需进行初始化,若变量未初始化,在编译时会输出报错信息。
775
776【反例】
777
778```ts
779@Builder
780function globalBuilder() {
781  Text('Hello World')
782}
783
784@Entry
785@Component
786struct CustomBuilderDemo {
787  build() {
788    Column() {
789      // 由于未对子组件ChildBuilder进行赋值,此处无论是编译还是编辑,均会报错。
790      ChildPage()
791    }
792  }
793}
794
795@Component
796struct ChildPage {
797  @Require @BuilderParam ChildBuilder: () => void = globalBuilder;
798
799  build() {
800    Column() {
801      this.ChildBuilder()
802    }
803  }
804}
805```
806
807对@Require装饰的变量进行外部传入初始化。
808
809【正例】
810
811```ts
812@Builder
813function globalBuilder() {
814  Text('Hello World')
815}
816
817@Entry
818@Component
819struct CustomBuilderDemo {
820  build() {
821    Column() {
822      ChildPage({ ChildBuilder: globalBuilder })
823    }
824  }
825}
826
827@Component
828struct ChildPage {
829  @Require @BuilderParam ChildBuilder: () => void = globalBuilder;
830
831  build() {
832    Column() {
833      this.ChildBuilder()
834    }
835  }
836}
837```
838
839### @BuilderParam装饰器初始化的值必须为@Builder
840
841使用`@State`装饰器装饰的变量,给子组件的`@BuilderParam`和`ChildBuilder`变量初始化时,编译时会输出报错信息。
842
843【反例】
844
845```ts
846@Builder
847function globalBuilder() {
848  Text('Hello World')
849}
850
851@Entry
852@Component
853struct CustomBuilderDemo {
854  @State message: string = '';
855
856  build() {
857    Column() {
858      // 子组件ChildBuilder接收@State装饰的变量,会出现编译和编辑报错
859      ChildPage({ ChildBuilder: this.message })
860    }
861  }
862}
863
864@Component
865struct ChildPage {
866  @BuilderParam ChildBuilder: () => void = globalBuilder;
867
868  build() {
869    Column() {
870      this.ChildBuilder()
871    }
872  }
873}
874```
875
876使用全局`@Builder`装饰的`globalBuilder()`方法为子组件`@BuilderParam`装饰的`ChildBuilder`变量进行初始化,编译时无报错,功能正常。
877
878【正例】
879
880```ts
881@Builder function globalBuilder() {
882  Text('Hello World')
883}
884@Entry
885@Component
886struct CustomBuilderDemo {
887  build() {
888    Column() {
889      ChildPage({ChildBuilder: globalBuilder})
890    }
891  }
892}
893
894@Component
895struct ChildPage {
896  @BuilderParam ChildBuilder: () => void = globalBuilder;
897  build() {
898    Column() {
899      this.ChildBuilder()
900    }
901  }
902}
903```