鸿蒙自定义组件开发完整指南【1】

2025-06-28 10:54:54
102次阅读
0个评论

第一篇:自定义组件基础

1.1 什么是自定义组件

自定义组件是鸿蒙ArkTS开发中的核心概念,它就像是搭积木时的一个个预制模块。想象一下,如果我们每次都要从最基础的砖块开始搭建房子,那会非常繁琐。自定义组件就是帮我们预先制作好的"房间模块",可以直接拿来使用,大大提高开发效率。

自定义组件的核心价值:

  • 封装性:将复杂的UI逻辑包装成简单易用的组件
  • 复用性:一次编写,多处使用,避免重复代码
  • 维护性:修改组件时,所有使用该组件的地方都会自动更新
  • 模块化:让代码结构更清晰,便于团队协作

在鸿蒙系统中,我们使用@Component装饰器来标识一个自定义组件。每个组件都必须实现build()方法来描述其UI结构,这就像是给组件画一张"设计图纸"。

1.2 创建第一个自定义组件

让我们从一个简单的按钮组件开始,学习如何创建自定义组件。这个按钮组件将支持不同的尺寸,并且可以自定义文本和点击事件。

设计思路:

  1. 定义组件的输入参数(按钮文本、尺寸、点击回调)
  2. 根据不同尺寸返回对应的样式配置
  3. 在build方法中构建UI结构
  4. 处理用户交互事件
@Component
export struct MyButton {
  @Prop buttonText: string = '默认按钮'
  @Prop buttonSize: 'small' | 'medium' | 'large' = 'medium'
  @Prop onButtonClick?: () => void

  private getSizeStyle() {
    switch (this.buttonSize) {
      case 'small':
        return { width: 80, height: 32, fontSize: 12 }
      case 'large':
        return { width: 120, height: 48, fontSize: 18 }
      default:
        return { width: 100, height: 40, fontSize: 14 }
    }
  }

  build() {
    Button(this.buttonText)
      .width(this.getSizeStyle().width)
      .height(this.getSizeStyle().height)
      .fontSize(this.getSizeStyle().fontSize)
      .backgroundColor('#3B82F6')
      .fontColor(Color.White)
      .borderRadius(8)
      .onClick(() => {
        if (this.onButtonClick) {
          this.onButtonClick()
        }
      })
  }
}

1.3 组件属性传递

在鸿蒙开发中,组件之间的数据传递是通过特殊的装饰器来实现的。这些装饰器就像是组件之间的"通信协议",规定了数据如何在父子组件之间流动。

主要的属性装饰器类型:

  • **@Prop**:单向数据流,父组件向子组件传递数据
  • **@State**:组件内部状态,数据变化时自动刷新UI
  • **@Link**:双向数据绑定,子组件可以修改父组件的数据
  • **@Provide/@Consume**:跨级组件通信,适用于深层嵌套场景

让我们通过具体例子来理解这些概念:

@Prop - 父向子传递

@Prop装饰器用于接收父组件传递的数据,这是最常用的数据传递方式。就像函数的参数一样,子组件通过@Prop声明需要接收哪些数据。

下面是一个用户卡片组件的例子,它接收用户名、头像和在线状态等信息:

@Component
struct UserCard {
  @Prop userName: string
  @Prop avatarUrl: string
  @Prop isOnline: boolean = false

  build() {
    Row() {
      Image(this.avatarUrl)
        .width(50)
        .height(50)
        .borderRadius(25)
      
      Column() {
        Text(this.userName)
          .fontSize(16)
          .fontWeight(FontWeight.Bold)
        
        Text(this.isOnline ? '在线' : '离线')
          .fontSize(12)
          .fontColor(this.isOnline ? '#10B981' : '#6B7280')
      }
      .alignItems(HorizontalAlign.Start)
      .margin({ left: 12 })
    }
    .padding(16)
    .backgroundColor('#FFFFFF')
    .borderRadius(12)
  }
}

@State - 组件内部状态

@State装饰器用于管理组件内部的状态数据。当状态发生变化时,鸿蒙框架会自动重新渲染相关的UI部分。这就像是给组件装上了"自动感应器",能够实时响应数据变化。

下面是一个计数器组件,演示了如何使用@State管理内部状态:

@Component
struct Counter {
  @State count: number = 0
  @State isActive: boolean = false

  build() {
    Column() {
      Text(`计数: ${this.count}`)
        .fontSize(24)
        .fontColor(this.isActive ? '#3B82F6' : '#374151')
      
      Row() {
        Button('-')
          .onClick(() => {
            this.count--
            this.isActive = this.count > 0
          })
        
        Button('+')
          .onClick(() => {
            this.count++
            this.isActive = this.count > 0
          })
      }
      .margin({ top: 16 })
    }
    .justifyContent(FlexAlign.Center)
    .width('100%')
    .height(200)
  }
}

1.4 组件使用示例

@Entry
@Component
struct HomePage {
  @State userList: Array<{name: string, avatar: string, online: boolean}> = [
    { name: '张三', avatar: $r('app.media.avatar1'), online: true },
    { name: '李四', avatar: $r('app.media.avatar2'), online: false }
  ]

  build() {
    Column() {
      Text('自定义组件示例')
        .fontSize(20)
        .fontWeight(FontWeight.Bold)
        .margin({ bottom: 20 })

      // 使用自定义按钮
      MyButton({
        buttonText: '小按钮',
        buttonSize: 'small',
        onButtonClick: () => {
          console.log('小按钮被点击')
        }
      })

      // 使用计数器
      Counter()

      // 使用用户卡片
      ForEach(this.userList, (user) => {
        UserCard({
          userName: user.name,
          avatarUrl: user.avatar,
          isOnline: user.online
        })
          .margin({ top: 12 })
      })
    }
    .padding(20)
    .width('100%')
    .height('100%')
  }
}
收藏00

登录 后评论。没有帐号? 注册 一个。