鸿蒙开发笔记-4-装饰器之@Builder、@LocalBuilder、@BuilderParam、wrapBuilder

112 阅读3分钟

一、核心概念解析

1. @Builder装饰器:UI复用的基石
  • 定义:将重复的UI逻辑抽象为独立函数,支持组件内或全局复用。
  • 特性
    • 作用域控制:组件内(私有)或全局定义。
    • 状态访问:组件内可通过this直接访问状态变量。
    • 参数传递:支持按值(默认)或按引用($$范式)传递状态变量。
  • 示例
    // 组件内私有构建函数
    @Component
    struct CounterComponent {
      @State count: number = 0;
      
      @Builder
      CounterUI() {
        Row() {
          Button('+').onClick(() => this.count++);
          Text(`Count: ${this.count}`)
        }
      }
      
      build() {
        Column() { this.CounterUI() }
      }
    }
    

2. @LocalBuilder装饰器:父子层级维护者
  • 定义:确保子组件在父组件上下文中构建,维持组件树层级关系。
  • 特性
    • 闭包特性:自动继承父组件状态,无需显式参数传递。
    • 动态插入:支持在父组件构建过程中动态插入同层级UI片段。
  • 示例
    @Component
    struct ParentComponent {
      @State showFooter: boolean = false;
      
      @LocalBuilder
      dynamicFooter() {
        if (this.showFooter) {
          Text("动态底部内容").fontSize(18)
        }
      }
      
      build() {
        Column() {
          Text("主体内容")
          this.dynamicFooter()
        }
      }
    }
    

3. @BuilderParam装饰器:动态插槽实现者
  • 定义:用于定义组件插槽,允许父组件向子组件注入自定义UI逻辑。
  • 特性
    • 类型安全:需严格匹配目标@Builder函数签名。
    • 初始化方式:支持参数传递、尾随闭包或箭头函数。
  • 示例
    // 子组件定义插槽
    @Component
    struct CardComponent {
      @BuilderParam content: () => void;
      
      build() {
        Column() { this.content() }
      }
    }
    
    // 父组件注入内容
    @Entry
    @Component
    struct App {
      @Builder
      cardContent() {
        Image($r('app.media.logo')).width(100)
      }
      
      build() {
        CardComponent({ content: this.cardContent })
      }
    }
    

4. wrapBuilder技术:构建器增强器
  • 定义:用于封装全局@Builder函数为可存储对象,支持动态调用。
  • 特性
    • 对象化封装:将全局构建函数转为WrappedBuilder对象。
    • 动态调用:支持存入数组并通过ForEach动态渲染。
  • 示例
    // 封装全局构建函数
    const wrappedBuilders = [
      wrapBuilder(HeaderBuilder),
      wrapBuilder(FooterBuilder)
    ]
    
    @Entry
    @Component
    struct MainPage {
      build() {
        Column() {
          ForEach(wrappedBuilders, (builder) => {
            builder.builder("动态标题")
          })
        }
      }
    }
    

二、四者对比分析表

维度@Builder@LocalBuilder@BuilderParamwrapBuilder
核心功能UI复用维护父子层级关系动态插槽构建器对象化封装
作用域组件内/全局组件内跨组件全局构建函数专用
状态访问直接访问组件状态继承父组件状态依赖参数传递不直接处理状态
参数传递值/引用传递自动继承上下文严格类型匹配支持值/引用类型参数
典型场景通用UI模板动态列表项/条件渲染可配置组件动态构建器数组调用
初始化限制必须组件内定义需用@Builder函数初始化仅支持全局@Builder封装

三、进阶应用模式

1. 组合式构建
// 全局构建函数 + 构建器增强
function ThemedButton(builder: () => Button) {
  return () => {
    const button = builder();
    button.backgroundColor(Color.Primary);
    return button;
  };
}

@Builder
function DefaultButton(text: string) {
  return ThemedButton(() => Button(text));
}
2. 层级化动态渲染
@Component
struct NestedComponent {
  @LocalBuilder
  renderItem(item: string) {
    Text(item).fontSize(18);
  }
  
  build() {
    Column() {
      ForEach(this.items, (item) => this.renderItem(item));
    }
  }
}
3. 插槽与状态联动
@Component
struct StatefulCard {
  @State message: string = "初始消息";
  @BuilderParam content: (message: string) => void;
  
  build() {
    Column() {
      this.content(this.message);
      Button("更新消息").onClick(() => this.message = "新消息");
    }
  }
}

四、总结

  • @Builder:适用于模块化UI复用,通过参数传递策略平衡灵活性与性能。
  • @LocalBuilder:解决父子组件层级关系问题,适合动态内容插入。
  • @BuilderParam:实现组件插槽机制,提升UI组合能力。
  • wrapBuilder:动态构建器调用的终极方案,特别适合可视化搭建场景。

我是今阳,如果想要进阶和了解更多的干货,欢迎关注微信公众号 “今阳说” 接收我的最新文章