五、Harmony OS 之 自定义组件

1.创建自定义组件

在ArkUI中,UI显示的内容均为组件,由框架直接提供的称为系统组件,由开发者定义的称为自定义组件。在进行UI界面开发时,通常不是简单的将系统组件进行组合使用,而是需要考虑代码可复用性、业务逻辑与UI分离,后续版本演进等因素。因此,将UI和部分业务逻辑封装成自定义组件是不可或缺的能力。

自定义组件具有以下特点:

可组合:允许开发者组合使用系统组件、及其属性和方法。

可重用:自定义组件可以被其他组件重用,并作为不同的实例在不同的父组件活容器中使用。

数据驱动UI更新:通过状态变量的改变,来驱动UI的刷新。

复制代码
/**
 * author:创客未来
 * copyright:com.ckFuture.hrb
 */
/**
 * 1:组件必须使用 @Component 装饰器
 * 2: @Entry 装饰哪个组件、哪个就呈现在页面上
 * 3: 被@Entry装饰的入口组件,build()中必须有且仅有一个**根容器**组件
 *    其他自定义组件,build()
 */
@Entry
@Component
struct Demo2 {
  @State message: string = '诗词学习'

  build() {
    Row() {
      Column() {
        Text(this.message)
          .fontSize(50)
          .fontWeight(FontWeight.Bold)
        itemComponent()
        itemComponent({content:'我是传递字符串'})
      }
      .width('100%')
    }
    .height('100%')
  }
}

@Component
struct itemComponent{
  // 自定义组件可以使用私有化变量(组件内部的变量都是私有化的,默认就是私有化) 传递参数
  private content: string = '默认字符串'
  build(){
    Row(){
      Image($r('app.media.icon'))
        .width(20)
        .height(20)
        .margin(15)
      Text(this.content)
    }
    .backgroundColor(Color.Pink)
    .borderRadius(25)
    .margin({
      top:15
    })
  }
}
复制代码

 

 组件内部点击事件

复制代码
/**
 * author:创客未来
 * copyright:com.ckFuture.hrb
 */
import FaultLogger from '@ohos.faultLogger'
/**
 * 1:组件必须使用 @Component 装饰器
 * 2: @Entry 装饰哪个组件、哪个就呈现在页面上
 * 3: 被@Entry装饰的入口组件,build()中必须有且仅有一个**根容器**组件
 *    其他自定义组件,build()
 */
@Entry
@Component
struct Demo2 {
  @State message: string = '诗词学习'

  build() {
    Row() {
      Column() {
        Text(this.message)
          .fontSize(50)
          .fontWeight(FontWeight.Bold)
        itemComponent()
        itemComponent({content:'我是传递字符串'})
      }
      .width('100%')
    }
    .height('100%')
  }
}

@Component
struct itemComponent{
  // 自定义组件可以使用私有化变量(组件内部的变量都是私有化的,默认就是私有化) 传递参数
  private content: string = '默认字符串'
  // 哪种情况可以驱动UI更新,@State
  @State isDone: boolean = false
  build(){
    Row(){
      Image(this.isDone?$r('app.media.iconOk'):$r('app.media.icon'))
        .width(20)
        .height(20)
        .margin(15)
      Text(this.content)
    }
    .backgroundColor(Color.Pink)
    .borderRadius(25)
    .margin({
      top:15
    })
    .onClick(()=>{
      //点击这一行修改图片
      this.isDone = !this.isDone
    })
  }
}
复制代码

 

点击自定义组件,文字变化效果

复制代码
@Component
struct itemComponent{
  // 自定义组件可以使用私有化变量(组件内部的变量都是私有化的,默认就是私有化) 传递参数
  private content: string = '默认字符串'
  // 哪种情况可以驱动UI更新,@State
  @State isDone: boolean = false
  build(){
    Row(){
      Image(this.isDone?$r('app.media.icon'):$r('app.media.icon'))
        .width(20)
        .height(20)
        .margin(15)
      Text(this.content)
        .decoration({
          type:this.isDone?TextDecorationType.LineThrough:TextDecorationType.None
        })
    }
    .backgroundColor(Color.Pink)
    .borderRadius(25)
    .margin({
      top:15
    })
    .onClick(()=>{
      //点击这一行修改图片
      this.isDone = !this.isDone
    })
  }
}
复制代码

 2.自定义组件构建函数

 @Builder装饰器

ArkUI还提供了一种更轻量的UI元素复用机制@Builder,@Builder所装饰的函数遵循build()函数语法规则,开发者可以将重复使用的UI元素抽象成一个方法,在build方法里调用。

2.1 组件内部的构建函数创建与调用

复制代码
/**
 * 自定义组件构建函数 @Builder
 */
@Entry
@Component
struct Demo3 {
  @State message: string = '@Builder'
  @State isDone:boolean = false

  /**
   * 构建函数
   * @param content 参数
   */
  @Builder item(content:string){
    Row(){
      Image(this.isDone?$r('app.media.icon'):$r('app.media.icon'))
        .width(20)
        .height(20)
        .margin(15)
      Text(content)
        .decoration({
          type:this.isDone?TextDecorationType.LineThrough:TextDecorationType.None
        })
    }
    .backgroundColor(Color.Pink)
    .borderRadius(25)
    .margin({
      top:15
    })
    .onClick(()=>{
      //点击这一行修改图片
      this.isDone = !this.isDone
    })
  }

  build() {
    Row() {
      Column() {
        Text(this.message)
          .fontSize(50)
          .fontWeight(FontWeight.Bold)
        //调用组件内部的构建函数
        this.item("轻舟已过万重山")
      }
      .width('100%')
    }
    .height('100%')
  }




}
复制代码

 

2.2 组件外部定义构建函数

组件外边定义构建函数好处是全局的,多个组件都可以引用。

复制代码
/**
 * 自定义组件构建函数(组件外部定义) @Builder
 */
@Entry
@Component
struct Demo3 {
  @State message: string = '@Builder'
  @State isDone:boolean = false



  build() {
    Row() {
      Column() {
        Text(this.message)
          .fontSize(50)
          .fontWeight(FontWeight.Bold)
        //调用组件内部的构建函数
        item("轻舟已过万重山")
      }
      .width('100%')
    }
    .height('100%')
  }

}

/**
 * 构建函数(外部)
 * 写在外面的自定义组件构建函数 方便多组件共同调用
 * @param content 参数
 */
@Builder function  item(content:string){
  Row(){
    Image(this.isDone?$r('app.media.icon'):$r('app.media.icon'))
      .width(20)
      .height(20)
      .margin(15)
    Text(content)
      .decoration({
        type:this.isDone?TextDecorationType.LineThrough:TextDecorationType.None
      })
  }
  .backgroundColor(Color.Pink)
  .borderRadius(25)
  .margin({
    top:15
  })
  .onClick(()=>{
    //点击这一行修改图片
    this.isDone = !this.isDone
  })
}
复制代码

 @Builder装饰器使用说明

参数传递规则说明

自定义构建函数的参数传递有按值传递和按引用传递两种,均需要遵守以下规则:

① 参数的类型必须与参数声明的类型一致,不允许undefind、null和返回 undefind、null的表达式。

② 在自定义构建函数内部,不允许改变参数值。如果需要改变参数值,且同步回调用点,建议使用@Link。

3.定义组件重用样式

@Styles装饰器

3.1 组件内部声明重用样式和调用

复制代码
/**
 * 自定义组件重用样式
 */
@Entry
@Component
struct Demo5 {
  @State message: string = '@Styles'
  /**
   * 定义重用样式
   * 目的是将重复公用的属性封装
   */
  @Styles commonStyle(){
    .width(200)
    .height(100)
    .backgroundColor(Color.Gray)
  }

  build() {
    Row() {
      Column({space:20}) {
        Text(this.message).fontSize(50).commonStyle()
        Button().commonStyle()
        Image('').commonStyle()
        Row(){}.commonStyle()
      }
      .width('100%')
    }
    .height('100%')
  }
}
复制代码

 

复制代码
/**
 * 自定义组件重用样式
 */
@Entry
@Component
struct Demo5 {
  @State message: string = '@Styles'
  /**
   * 定义重用样式
   * 目的是将重复公用的属性封装
   */
  // @Styles commonStyle(){
  //   .width(200)
  //   .height(100)
  //   .backgroundColor(Color.Gray)
  // }

  build() {
    Row() {
      Column({space:20}) {
        Text(this.message).fontSize(50).commonStyle()
        Button().commonStyle()
        Image('').commonStyle()
        Row(){}.commonStyle()
      }
      .width('100%')
    }
    .height('100%')
  }
}

//外部通过样式函数
@Styles function commonStyle(){
  .width(250)
  .height(50)
  .backgroundColor(Color.Gray)
}
复制代码

 

 整体代码

复制代码
/**
 * 自定义样式函数使用装饰器 @Styles
 * 内部函数优先级 > 外部函数
 * 内部不需要function关键字
 * 外部需要function关键字
 * 弊端:只能写通用样式,不能传参。
 */
@Entry
@Component
struct Demo5 {
  @State message: string = '@Styles'
  /**
   * 定义重用样式函数 不需要function
   * 目的是将重复公用的属性封装
   */
  @Styles commonStyle(){
    .width(200)
    .height(100)
    .backgroundColor(Color.Gray)
  }

  build() {
    Row() {
      Column({space:20}) {
        Text(this.message).fontSize(50).commonStyle()
        Button().commonStyle()
        Image('').commonStyle()
        Row(){}.commonStyle()
      }
      .width('100%')
    }
    .height('100%')
  }
}

//外部通过样式函数
@Styles function commonStyle(){
  .width(250)
  .height(50)
  .backgroundColor(Color.Gray)
}
复制代码

4.定义扩展组件样式

@Extend装饰器

语法

@Extend(UIComponentName) function functionName{...}

使用规则

① 和@Style不同,@Extend仅支持定义在全局,不支持在组件内部定义。

② 和@Style不同,@Extend支持封装指定的组件的私有属性和私有事件和预定义相同组件的@Extend的方法。

③ 和@Style不同,@Extend装饰的方法支持参数,开发者可以在调用时传递参数,调用遵循TS方法传值调用。

复制代码
/**
 * 定义扩展组件样式 @Extend
 */
@Entry
@Component
struct Demo6 {
  @State message: string = '@Extend'
  @State count: number = 0
  build() {
    Row() {
      Column() {
        Text(this.message)
          .fontSize(50)
          .fontWeight(FontWeight.Bold)
        Text('HarmonyOS4.0').textStyle(40,Color.Blue)
        Text('一件三联').textStyle(40,'red')
        Text('下次一定').textStyle(20,'#ababab')
        Text('干啥玩意').textStyle(50,Color.Pink)
        Button(this.count.toString()).btnStyle(()=>{
          this.count++
        })
      }
      .width('100%')
    }
    .height('100%')
  }
}
/**
 * 定义 Text组件的扩展组件样式
 */
@Extend(Text) function sizeColor(fs: number,fc: Color|string){
  .fontSize(fs)
  .fontColor(fc)
}

@Extend(Text) function textStyle(fs: number,fc: Color|string){
  .sizeColor(fs,fc)
  .fontWeight(FontWeight.Bold)
}
//定义 Button组件的扩展样式
//传递函数 click:()=>void 或者 click:Function
@Extend(Button) function  btnStyle(click:()=>void){
  .fontSize(40)
  .width(150)
  .height(50)
  .onClick(()=>{
    click()
  })
}
复制代码

 

 

 

posted @   创客未来  阅读(461)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
点击右上角即可分享
微信分享提示