• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# wrapBuilder:封装全局@Builder
2
3  当开发者在一个struct内使用了多个全局@Builder函数,来实现UI的不同效果时,多个全局@Builder函数会使代码维护起来非常困难,并且页面不整洁。此时,开发者可以使用wrapBuilder来封装全局@Builder。
4
5
6> **说明:**
7>
8> 从API version 11开始使用。
9
10当@Builder方法赋值给变量或者数组后,赋值的变量或者数组在UI方法中无法使用。
11
12```ts
13@Builder
14function builderElement() {}
15
16let builderArr: Function[] = [builderElement];
17@Builder
18function testBuilder() {
19  ForEach(builderArr, (item: Function) => {
20    item();
21  })
22}
23```
24
25在上述代码中,builderArr是一个@Builder方法组成的数组, 在ForEach中取每一项@Builder方法时会出现@Builder方法在UI方法中无法使用的错误。
26
27 为了解决这一问题,引入wrapBuilder作为全局@Builder封装函数。wrapBuilder的参数返回WrappedBuilder对象,实现[全局\@Builder](arkts-builder.md#全局自定义构建函数)可以进行赋值和传递。
28
29## 接口说明
30
31wrapBuilder是一个模板函数,返回一个`WrappedBuilder`对象。
32
33```ts
34declare function wrapBuilder< Args extends Object[]>(builder: (...args: Args) => void): WrappedBuilder;
35```
36同时 `WrappedBuilder`对象也是一个模板类。
37
38```ts
39declare class WrappedBuilder< Args extends Object[]> {
40  builder: (...args: Args) => void;
41
42  constructor(builder: (...args: Args) => void);
43}
44```
45
46
47>说明:模板参数`Args extends Object[]`是需要包装的builder函数的参数列表
48
49使用方法:
50
51```ts
52let builderVar: WrappedBuilder<[string, number]> = wrapBuilder(MyBuilder)
53let builderArr: WrappedBuilder<[string, number]>[] = [wrapBuilder(MyBuilder)] //可以放入数组
54```
55
56
57
58## 限制条件
59
60wrapBuilder方法只能传入[全局\@Builder](arkts-builder.md#全局自定义构建函数)方法。
61
62wrapBuilder方法返回的WrappedBuilder对象的builder属性方法只能在struct内部使用。
63
64
65
66## @Builder方法赋值给变量
67
68把@Builder装饰器装饰的方法MyBuilder作为wrapBuilder的参数,再将wrapBuilder赋值给变量globalBuilder,用来解决@Builder方法赋值给变量后无法被使用的问题。
69
70```ts
71@Builder
72function MyBuilder(value: string, size: number) {
73  Text(value)
74    .fontSize(size)
75}
76
77let globalBuilder: WrappedBuilder<[string, number]> = wrapBuilder(MyBuilder);
78
79@Entry
80@Component
81struct Index {
82  @State message: string = 'Hello World';
83
84  build() {
85    Row() {
86      Column() {
87        globalBuilder.builder(this.message, 50)
88      }
89      .width('100%')
90    }
91    .height('100%')
92  }
93}
94```
95
96##  @Builder方法赋值给变量在UI语法中使用
97
98自定义组件Index使用ForEach来进行不同\@Builder函数的渲染,可以使用builderArr声明的wrapBuilder数组进行不同\@Builder函数效果体现。整体代码会较整洁。
99
100```
101@Builder
102function MyBuilder(value: string, size: number) {
103  Text(value)
104    .fontSize(size)
105}
106
107@Builder
108function YourBuilder(value: string, size: number) {
109  Text(value)
110    .fontSize(size)
111    .fontColor(Color.Pink)
112}
113
114const builderArr: WrappedBuilder<[string, number]>[] = [wrapBuilder(MyBuilder), wrapBuilder(YourBuilder)];
115
116
117@Entry
118@Component
119struct Index {
120  @Builder testBuilder() {
121    ForEach(builderArr, (item: WrappedBuilder<[string, number]>) => {
122      item.builder('Hello World', 30)
123    }
124
125    )
126  }
127
128  build() {
129    Row() {
130      Column() {
131        this.testBuilder()
132      }
133      .width('100%')
134    }
135    .height('100%')
136  }
137}
138```
139
140## 引用传递
141
142通过按引用传递的方式传入参数,会触发UI的刷新。
143
144```ts
145class Tmp {
146  paramA2: string = 'hello';
147}
148
149@Builder function overBuilder(param: Tmp) {
150  Column(){
151    Text(`wrapBuildervalue:${param.paramA2}`)
152  }
153}
154
155const wBuilder: WrappedBuilder<[Tmp]> = wrapBuilder(overBuilder);
156
157@Entry
158@Component
159struct Parent{
160  @State label: Tmp = new Tmp();
161  build(){
162    Column(){
163      wBuilder.builder({paramA2: this.label.paramA2})
164      Button('Click me').onClick(() => {
165        this.label.paramA2 = 'ArkUI';
166      })
167    }
168  }
169}
170```
171
172## 错误场景
173
174### wrapBuilder必须传入被@Builder修饰的全局函数。
175
176```ts
177function MyBuilder() {
178
179}
180
181const globalBuilder: WrappedBuilder<[string, number]> = wrapBuilder(MyBuilder);
182
183@Entry
184@Component
185struct Index {
186  @State message: string = 'Hello World';
187
188  build() {
189    Row() {
190      Column() {
191        Text(this.message)
192          .fontSize(50)
193          .fontWeight(FontWeight.Bold)
194        globalBuilder.builder(this.message, 30)
195      }
196      .width('100%')
197    }
198    .height('100%')
199  }
200}
201```
202
203### 重复定义wrapBuilder失效
204
205通过wrapBuilder(MyBuilderFirst)初始化定义builderObj之后,再次对builderObj进行赋值wrapBuilder(MyBuilderSecond)会不起作用,只生效第一次定义的wrapBuilder(MyBuilderFirst)。
206
207```ts
208@Builder
209function MyBuilderFirst(value: string, size: number) {
210  Text('MyBuilderFirst:' + value)
211    .fontSize(size)
212}
213
214@Builder
215function MyBuilderSecond(value: string, size: number) {
216  Text('MyBuilderSecond:' + value)
217    .fontSize(size)
218}
219
220interface BuilderModel {
221  globalBuilder: WrappedBuilder<[string, number]>;
222}
223
224@Entry
225@Component
226struct Index {
227  @State message: string = 'Hello World';
228  @State builderObj: BuilderModel = { globalBuilder: wrapBuilder(MyBuilderFirst) };
229
230  aboutToAppear(): void {
231    setTimeout(() => {
232      this.builderObj.globalBuilder = wrapBuilder(MyBuilderSecond);
233    },1000)
234  }
235
236  build() {
237    Row() {
238      Column() {
239        this.builderObj.globalBuilder.builder(this.message, 20)
240      }
241      .width('100%')
242    }
243    .height('100%')
244  }
245}
246```