1# \@BuilderParam:引用\@Builder函数 2 3 4当开发者创建了自定义组件,并想对该组件添加特定功能时,例如在自定义组件中添加一个点击跳转操作。若直接在组件内嵌入事件方法,将会导致所有引入该自定义组件的地方均增加了该功能。为解决此问题,ArkUI引入了\@BuilderParam装饰器,\@BuilderParam用来装饰指向\@Builder方法的变量,开发者可在初始化自定义组件时对此属性进行赋值,为自定义组件增加特定的功能。该装饰器用于声明任意UI描述的一个元素,类似slot占位符。 5 6 7> **说明:** 8> 9> 从API version 9开始,该装饰器支持在ArkTS卡片中使用。 10 11 12## 装饰器使用说明 13 14 15### 初始化\@BuilderParam装饰的方法 16 17\@BuildParam装饰的方法只能被自定义构建函数(\@Builder装饰的方法)初始化。 18 19- 使用所属自定义组件的自定义构建函数或者全局的自定义构建函数,在本地初始化\@BuilderParam。 20 21 ```ts 22 @Builder function GlobalBuilder0() {} 23 24 @Component 25 struct Child { 26 @Builder doNothingBuilder() {}; 27 28 @BuilderParam aBuilder0: () => void = this.doNothingBuilder; 29 @BuilderParam aBuilder1: () => void = GlobalBuilder0; 30 build(){} 31 } 32 ``` 33 34- 用父组件自定义构建函数初始化子组件\@BuildParam装饰的方法。 35 36 ```ts 37 @Component 38 struct Child { 39 @BuilderParam aBuilder0: () => void; 40 41 build() { 42 Column() { 43 this.aBuilder0() 44 } 45 } 46 } 47 48 @Entry 49 @Component 50 struct Parent { 51 @Builder componentBuilder() { 52 Text(`Parent builder `) 53 } 54 55 build() { 56 Column() { 57 Child({ aBuilder0: this.componentBuilder }) 58 } 59 } 60 } 61 ``` 62 63 64- 需注意this指向正确。 65 66 以下示例中,Parent组件在调用this.componentBuilder()时,this.label指向其所属组件,即“Parent”。\@Builder componentBuilder()传给子组件\@BuilderParam aBuilder0,在Child组件中调用this.aBuilder0()时,this.label指向在Child的label,即“Child”。 67 68 > **说明:** 69 > 70 > 开发者谨慎使用bind改变函数调用的上下文,可能会使this指向混乱。 71 72 ```ts 73 @Component 74 struct Child { 75 label: string = `Child` 76 @BuilderParam aBuilder0: () => void; 77 78 build() { 79 Column() { 80 this.aBuilder0() 81 } 82 } 83 } 84 85 @Entry 86 @Component 87 struct Parent { 88 label: string = `Parent` 89 90 @Builder componentBuilder() { 91 Text(`${this.label}`) 92 } 93 94 build() { 95 Column() { 96 this.componentBuilder() 97 Child({ aBuilder0: this.componentBuilder }) 98 } 99 } 100 } 101 ``` 102 103 104## 使用场景 105 106 107### 参数初始化组件 108 109\@BuilderParam装饰的方法可以是有参数和无参数的两种形式,需与指向的\@Builder方法类型匹配。\@BuilderParam装饰的方法类型需要和\@Builder方法类型一致。 110 111 112```ts 113@Builder function GlobalBuilder1($$ : {label: string }) { 114 Text($$.label) 115 .width(400) 116 .height(50) 117 .backgroundColor(Color.Blue) 118} 119 120@Component 121struct Child { 122 label: string = 'Child' 123 // 无参数类,指向的componentBuilder也是无参数类型 124 @BuilderParam aBuilder0: () => void; 125 // 有参数类型,指向的GlobalBuilder1也是有参数类型的方法 126 @BuilderParam aBuilder1: ($$ : { label : string}) => void; 127 128 build() { 129 Column() { 130 this.aBuilder0() 131 this.aBuilder1({label: 'global Builder label' } ) 132 } 133 } 134} 135 136@Entry 137@Component 138struct Parent { 139 label: string = 'Parent' 140 141 @Builder componentBuilder() { 142 Text(`${this.label}`) 143 } 144 145 build() { 146 Column() { 147 this.componentBuilder() 148 Child({ aBuilder0: this.componentBuilder, aBuilder1: GlobalBuilder1 }) 149 } 150 } 151} 152``` 153 154 155### 尾随闭包初始化组件示例 156 157在自定义组件中使用\@BuilderParam装饰的属性时也可通过尾随闭包进行初始化。在初始化自定义组件时,组件后紧跟一个大括号“{}”形成尾随闭包场景。 158 159> **说明:** 160> 161> 此场景下自定义组件内有且仅有一个使用\@BuilderParam装饰的属性。 162 163开发者可以将尾随闭包内的内容看做\@Builder装饰的函数传给\@BuilderParam。示例如下: 164 165 166```ts 167// xxx.ets 168@Component 169struct CustomContainer { 170 @Prop header: string; 171 @BuilderParam closer: () => void 172 173 build() { 174 Column() { 175 Text(this.header) 176 .fontSize(30) 177 this.closer() 178 } 179 } 180} 181 182@Builder function specificParam(label1: string, label2: string) { 183 Column() { 184 Text(label1) 185 .fontSize(30) 186 Text(label2) 187 .fontSize(30) 188 } 189} 190 191@Entry 192@Component 193struct CustomContainerUser { 194 @State text: string = 'header'; 195 196 build() { 197 Column() { 198 // 创建CustomContainer,在创建CustomContainer时,通过其后紧跟一个大括号“{}”形成尾随闭包 199 // 作为传递给子组件CustomContainer @BuilderParam closer: () => void的参数 200 CustomContainer({ header: this.text }) { 201 Column() { 202 specificParam('testA', 'testB') 203 }.backgroundColor(Color.Yellow) 204 .onClick(() => { 205 this.text = 'changeHeader'; 206 }) 207 } 208 } 209 } 210} 211``` 212