HarmonyOS鸿蒙Next中如何实现自定义通用组件?@BuilderParam和@Component

HarmonyOS鸿蒙Next中如何实现自定义通用组件?@BuilderParam@Component 多个页面使用相似的卡片样式,希望封装成通用组件,支持自定义内容。

3 回复

原理解析

HarmonyOS ArkUI提供了组件化开发能力:

  • @Component装饰器定义自定义组件
  • @BuilderParam接收外部传入的UI构建函数
  • 通过属性传递配置参数

解决步骤

步骤1:定义通用卡片组件

import { Colors, BorderRadius, Spacing } from '../constants/Colors';

[@Component](/user/Component)
export struct CardView {
  [@BuilderParam](/user/BuilderParam) content: () => void;  // 接收外部UI内容
  padding: number = Spacing.lg;
  marginH: number = Spacing.xl;
  marginV: number = Spacing.md;

  build() {
    Column() {
      if (this.content) {
        this.content()
      }
    }
    .width('100%')
    .padding(this.padding)
    .margin({ left: this.marginH, right: this.marginH, top: this.marginV, bottom: this.marginV })
    .backgroundColor(Colors.cardBackground)
    .borderRadius(BorderRadius.lg)
    .border({ width: 1, color: Colors.border })
    .shadow({ radius: 4, color: '#0000000a', offsetY: 2 })
  }
}

步骤2:定义渐变卡片组件

[@Component](/user/Component)
export struct GradientCard {
  [@BuilderParam](/user/BuilderParam) content: () => void;
  padding: number = Spacing.xl;
  marginH: number = Spacing.xl;

  build() {
    Stack() {
      // 渐变背景
      Column()
        .width('100%')
        .height('100%')
        .linearGradient({
          angle: 135,
          colors: [[Colors.primary, 0], [Colors.primaryLight, 1]]
        })
        .borderRadius(BorderRadius.xl)

      // 内容
      Column() {
        if (this.content) {
          this.content()
        }
      }
      .width('100%')
      .padding(this.padding)
    }
    .width('100%')
    .margin({ left: this.marginH, right: this.marginH })
    .borderRadius(BorderRadius.xl)
    .shadow({ radius: 8, color: '#06575840', offsetY: 4 })
  }
}

步骤3:使用自定义组件

import { CardView, GradientCard } from '../components/CardView';

@Entry
[@Component](/user/Component)
struct MyPage {
  build() {
    Column() {
      // 使用普通卡片
      CardView({ padding: 16 }) {
        Column({ space: 8 }) {
          Text('卡片标题').fontSize(16).fontWeight(FontWeight.Bold)
          Text('卡片内容描述').fontSize(14).fontColor('#666')
        }
      }
      
      // 使用渐变卡片
      GradientCard() {
        Column({ space: 8 }) {
          Text('渐变卡片').fontSize(18).fontColor('#fff')
          Text('漂亮的渐变背景').fontSize(14).fontColor('#ddd')
        }
      }
    }
  }
}

步骤4:定义颜色常量(统一管理)

// Colors.ets
export const Colors = {
  primary: '#065758',
  primaryLight: '#00999F',
  cardBackground: '#ffffff',
  textPrimary: '#0d121b',
  textSecondary: '#6b7280',
  border: '#e5e7eb'
}

export const Spacing = {
  sm: 8,
  md: 12,
  lg: 16,
  xl: 20
}

export const BorderRadius = {
  md: 8,
  lg: 12,
  xl: 16
}

效果图

封装通用组件 → 统一样式管理 → 多处复用 → 修改一处全局生效

更多关于HarmonyOS鸿蒙Next中如何实现自定义通用组件?@BuilderParam和@Component的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


在HarmonyOS Next中,使用@BuilderParam装饰器实现自定义通用组件。@BuilderParam用于声明自定义构建函数类型的属性,允许父组件传递UI构建逻辑给子组件。子组件通过@BuilderParam属性接收并调用该构建函数,实现动态UI组合。@Component装饰器用于定义可复用的自定义组件,封装内部UI结构和行为。两者结合可实现灵活、可复用的通用组件。

在HarmonyOS Next中,使用[@BuilderParam](/user/BuilderParam)[@Component](/user/Component)装饰器是实现自定义通用组件的核心方案,尤其适合封装可复用的卡片式UI。

核心实现步骤:

  1. 定义组件结构(@Component 使用[@Component](/user/Component)创建可复用的UI组件框架,定义卡片的固定布局(如标题栏、边框等)。

    [@Component](/user/Component)
    struct CustomCard {
      // 定义占位区域
    }
    
  2. 声明动态内容接口(@BuilderParam 在组件内部使用[@BuilderParam](/user/BuilderParam)声明一个或多个插槽,用于接收外部传入的自定义UI内容。

    [@Component](/user/Component)
    struct CustomCard {
      [@BuilderParam](/user/BuilderParam) contentBuilder: () => void
      // 或声明多个插槽:[@BuilderParam](/user/BuilderParam) headerBuilder: () => void
    }
    
  3. 在组件布局中调用 在组件的build()方法中,通过调用this.contentBuilder()来渲染外部传入的UI。

    build() {
      Column() {
        // 固定部分
        Text('卡片标题')
        // 动态内容部分
        this.contentBuilder()
      }
    }
    
  4. 外部使用组件并传入内容 在使用该组件的页面中,通过[@Builder](/user/Builder)定义要插入的自定义UI,并传递给组件。

    [@Builder](/user/Builder)
    function MyCustomContent() {
      Text('这是自定义内容')
      Button('按钮')
    }
    
    // 在页面中调用
    CustomCard({
      contentBuilder: this.MyCustomContent
    })
    

关键优势:

  • 高复用性:一次封装,多处使用。
  • 强灵活性:通过[@BuilderParam](/user/BuilderParam)允许外部完全控制部分区域的UI和逻辑。
  • 类型安全:ArkTS的静态类型检查确保传递内容的正确性。

典型应用场景:

  • 统一视觉规范的卡片、弹窗、设置项。
  • 列表项模板。
  • 带有可变头部/底部/内容的容器组件。

这种方式实现了组件框架与具体内容的解耦,是HarmonyOS Next中构建可复用UI模块的标准实践。

回到顶部