本文同步发表于我的微信公众号,微信搜索 程语新视界 即可关注,每个工作日都有文章更新

   wrapBuilder是鸿蒙ArkUI提供的一个模板函数,用于封装全局@Builder函数,返回一个WrappedBuilder对象。它解决了@Builder函数在赋值给变量或数组后无法在UI方法中直接使用的痛点。

版本支持说明

  • API Version 11:开始支持wrapBuilder

  • API Version 12:支持在元服务中使用

  • API Version 22+:推荐使用mutableBuilder(支持二次赋值后刷新UI)

二、为什么需要wrapBuilder?

2.1 传统@Builder的使用限制

@Builder方法赋值给变量或数组后,在UI方法中无法直接调用:

@Builder
function builderElement() {}

let builderArr: Function[] = [builderElement];

@Builder
function testBuilder() {
  ForEach(builderArr, (item: Function) => {
    item(); // 错误:@Builder方法无法在UI方法中使用
  })
}

2.2 wrapBuilder的解决方案

wrapBuilder@Builder函数包装为WrappedBuilder对象,使其可以:

  • 赋值给变量

  • 放入数组

  • 作为属性传递给其他组件

  • 在UI语法中正常调用

三、核心API

3.1 wrapBuilder函数签名

declare function wrapBuilder<Args extends Object[]>(
  builder: (...args: Args) => void
): WrappedBuilder<Args>;

模板参数说明

  • Args extends Object[]:必须匹配被包装@Builder函数参数的类型

3.2 WrappedBuilder类结构

declare class WrappedBuilder<Args extends Object[]> {
  builder: (...args: Args) => void;
  constructor(builder: (...args: Args) => void);
}

重要属性

  • builder:实际的构建函数,只能在struct内部使用

四、使用示例

4.1 基础用法:@Builder方法赋值给变量

@Builder
function myBuilder(value: string, size: number) {
  Text(value)
    .fontSize(size)
}

// 包装为WrappedBuilder对象
let globalBuilder: WrappedBuilder<[string, number]> = wrapBuilder(myBuilder);

@Entry
@Component
struct TestIndex {
  @State message: string = 'Hello World';

  build() {
    Row() {
      Column() {
        globalBuilder.builder(this.message, 50) // 正常调用
      }
      .width('100%')
    }
    .height('100%')
  }
}

4.2 高级用法:@Builder数组与ForEach渲染

@Builder
function myBuilder0(value: string, size: number) {
  Text(value)
    .fontSize(size)
    .fontColor(Color.Blue)
}

@Builder
function yourBuilder(value: string, size: number) {
  Text(value)
    .fontSize(size)
    .fontColor(Color.Pink)
}

// 创建包装后的Builder数组
const builderArr: WrappedBuilder<[string, number]>[] = [
  wrapBuilder(myBuilder0),
  wrapBuilder(yourBuilder)
];

@Entry
@Component
struct IndexItem {
  @Builder
  IndexItem() {
    ForEach(builderArr, (item: WrappedBuilder<[string, number]>) => {
      item.builder('Hello World', 30); // 循环渲染不同样式的Builder
    })
  }

  build() {
    Row() {
      Column() {
        this.IndexItem();
      }
      .width('100%')
    }
    .height('100%')
  }
}

4.3 组件间传递:作为接口属性

@Builder
function MyBuilder(value: string, size: number) {
  Text(value)
    .fontSize(size)
}

// 定义接口包含WrappedBuilder属性
interface ChildOptions {
  wrappedBuilder: WrappedBuilder<[string, number]>;
}

@Entry
@Component
struct Index {
  childOptions: ChildOptions = {
    wrappedBuilder: wrapBuilder(MyBuilder) // 包装后赋值
  };

  build() {
    Row() {
      Column() {
        Child({ options: this.childOptions })
      }
      .width('100%')
    }
    .height('100%')
  }
}

@Component
struct Child {
  @Prop options: ChildOptions;

  build() {
    this.options.wrappedBuilder.builder('Hello', 20); // 子组件调用
  }
}

4.4 响应式更新:引用传递与状态联动

class Tmp {
  public paramA2: string = 'hello';
}

@Builder
function overBuilder(param: Tmp) {
  Column() {
    Text(`wrapBuilder value: ${param.paramA2}`)
  }
}

const wBuilder: WrappedBuilder<[Tmp]> = wrapBuilder(overBuilder);

@Entry
@Component
struct Parent {
  @State label: Tmp = new Tmp();

  build() {
    Column() {
      wBuilder.builder({ paramA2: this.label.paramA2 })
      Button('Click me').onClick(() => {
        this.label.paramA2 = 'ArkUI'; // 状态更新触发UI刷新
      })
    }
  }
}

五、使用限制

  1. 仅支持全局@BuilderwrapBuilder只能传入用@Builder装饰的全局函数

  2. builder属性使用范围WrappedBuilderbuilder属性方法仅限在struct内部使用

  3. 模板参数匹配:必须确保模板参数类型与原始@Builder函数参数类型完全匹配

六、wrapBuilder vs mutableBuilder

6.1 版本演进

  • API 22之前:使用wrapBuilder处理全局Builder的赋值和传递

  • API 22+:推荐使用mutableBuilder,支持更灵活的重赋值和UI刷新

6.2 建议

  • 如果应用需要兼容较低API版本,使用wrapBuilder

  • 如果应用面向API 22+且需要动态更换Builder,考虑mutableBuilder

总结

wrapBuilder是鸿蒙ArkUI中处理全局@Builder函数的重要工具,它通过包装机制解决了以下问题:

  1. 代码组织问题:将分散的全局Builder统一管理

  2. 赋值传递问题:使Builder可以安全地赋值给变量、数组和接口属性

  3. UI调用问题:确保包装后的Builder能在UI语法中正常使用

  4. 组件通信问题:方便在父子组件间传递UI构建逻辑

通过合理使用wrapBuilder,可以构建更加模块化、可维护的ArkUI应用,特别是在需要动态切换UI构建逻辑的复杂场景中,其价值更加凸显。

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐