十一、动态构建UI元素 原创

亚鲁鲁666
发布于 2024-12-10 22:17
浏览
0收藏

装饰器@Builder

装饰器@BuilderParam

​<font style="color:rgba(0, 0, 0, 0.9);">BuilderParam</font>​​ 该装饰器用于声明任意UI描述的一个元素,类似slot占位符。

​链接​

简而言之:就是自定义组件允许外部传递 UI

// SonCom 的实现略

@Entry
@Component
struct Index {
  build() {
    Column({ space: 15 }) {
      SonCom() {
        // 直接传递进来(尾随闭包)
        Button('传入的结构')
          .onClick(() => {
            AlertDialog.show({ message: '点了 Button' })
          })
      }
    }
  }
}

2.1单个@BuilderParam参数

:::info 使用尾随闭包的方式传入:

  • 组件内有且仅有一个使用 @BuilderParam 装饰的属性,即可使用尾随闭包
  • 内容直接在 {} 传入即可

注意:

  • 此场景下自定义组件不支持使用通用属性。

:::

@Component
struct SonCom {
  // 1.设置默认 的 Builder,避免外部不传入
  @Builder
  defaultBuilder() {
    Text('默认的内容')
  }
  
  // 2.定义 BuilderParam 接受外部传入的 ui,并设置默认值
  @BuilderParam ContentBuilder: () => void = this.defaultBuilder



  build() {
    Column() {
      // 3. 使用 @BuilderParam 装饰的成员变量
      this.ContentBuilder()
    }
    .width(300)
    .height(200)
    .border({ width: .5 })
  }
}


// 使用自定义组件时,就可以使用如下方式传递 UI
// 不传递时会使用默认值
SonCom(){
  // 传入的 UI
}

:::info

  1. 添加自定义组件:
  1. 定义默认的 Builder
  2. 添加BuilderParam,添加类型,并设置默认的 Builder
  3. 组件内部使用 BuilderParam
  1. 外部使用自定义组件,分别测试传递,不传递 UI 的情况

:::

@Component
struct SonCom {
  // 由外部传入 UI
  @BuilderParam ContentBuilder: () => void = this.defaultBuilder

  // 设置默认 的 Builder,避免外部不传入
  @Builder
  defaultBuilder() {
    Text('默认的内容')
  }

  //自定义组件的build,
  build() {
    Column() {
      //自定义组件通过@BuilderParam接收到的参数, 放在这里了
      this.ContentBuilder()
    }
    .width(300)
    .height(200)
    .border({ width: .5 })
  }
}

@Entry
@Component
struct Index {
  build() {
    Column({ space: 15 }) {
      //自定义组件的单个组件参数通过尾随闭包传入
      SonCom() {
        // 直接传递进来
        Button('传入的结构')
          .onClick(() => {
            AlertDialog.show({ message: '点了 Button' })
          })
      }
    }
  }
}
import text from '@ohos.graphics.text';

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

  build() {
    Column() {
      //4.1调用自定义组件, 什么也不传
      myCom()
      //4.2调用自定义组件, 传一个text
      myCom(){
        Text('新传入的text')
      }
      //4.3调用自定义组件, 传一个text
      myCom(){
        Button('新传入的button')
      }
    }
  }
}

@Component
struct myCom {

  //1.先写默认的构造器, 防止外部不传入
  @Builder
  defultBuilder(){
    Text('默认的组件')
  }

  //2.定义可以接受组件参数的Builderparam
  @BuilderParam
  newBuider:()=>void     = this.defultBuilder


  build() {
    Column(){
      //3.在自定义组件中使用Builderparam
      this.newBuider()
    }
  }
}

2.2多个@BuilderParam参数

子组件有多个BuilderParam,必须通过参数的方式来传入

:::info 核心步骤:

  1. 自定义组件-定义:
  1. 添加多个 @BuilderParam ,并定义默认值
  1. 自定义组件-使用
  1. 通过参数的形式传入多个 Builder,比如

SonCom({ titleBuilder: this.fTitleBuilder, contentBuilder: this.fContentBuilder })

:::

@Component
struct SonCom {
  // 由外部传入 UI
  @BuilderParam titleBuilder: () => void = this.titleDefaultBuilder
  @BuilderParam contentBuilder: () => void = this.contentDefaultBuilder

  // 设置默认 的 Builder,避免外部不传入
  @Builder
  titleDefaultBuilder() {
    Text('默认标题')
  }

  @Builder
  contentDefaultBuilder() {
    Text('默认内容')
  }

  build() {
    Column() {
      Row() {
        this.titleBuilder()
      }
      .layoutWeight(1)

      Divider()
      Row() {
        this.contentBuilder()
      }
      .layoutWeight(1)

    }
    .width(300)
    .height(200)
    .border({ width: .5 })
  }
}

@Entry
@Component
struct Index {
  @Builder
  fTitleBuilder() {
    Text('传入的标题')
      .fontSize(20)
      .fontWeight(600)
      .fontColor(Color.White)
      .backgroundColor(Color.Blue)
      .padding(10)
  }

  @Builder
  fContentBuilder() {
    Text('传入的标题')
      .fontSize(20)
      .fontWeight(600)
      .fontColor(Color.White)
      .backgroundColor(Color.Blue)
      .padding(10)
  }

  build() {
    Column({ space: 15 }) {
      //{@BuilderParam的参数名:自己组件内的@Builder构建函数名}
      SonCom({ titleBuilder: this.fTitleBuilder, contentBuilder: this.fContentBuilder })
    }
  }
}

装饰器@Styles

装饰器@Extend

装饰器@CustomDialog

自定义组件@Component

自定义组件基础

在ArkUI中,UI显示的内容均为组件,

由框架直接提供的称为系统组件,由开发者定义的称为自定义组件。

相比于之前学习的轻量级 UI 复用机制 @Builder,

自定义组件的功能更为强大,因为自定义组件可以通过​​<font style="color:rgba(0, 0, 0, 0.9);">@Prop @Link @BuilderParam</font>​​实现父子组件进行传递组件和参数。

开发中如果要进行 UI 或业务逻辑进行复用,需要掌握自定义组件的能力。

// HelloComponent 的实现略,后续补充

//父组件
@Entry
@Component
struct CustomComponentDemo {
  build() {
    Column() {
      // 自定义组件
      HelloComponent()
      HelloComponent()
    }
  }
}

//子组件
@Component
struct HelloComponent {
  
}

1.1基本使用

:::success 说明

自定义组件名、类名、函数名不能和系统组件名相同。

:::

// 定义
@Component
struct MyComponent {
  // 状态变量
  @State message:string =''
  build(){
    // .... 描述 UI
  }
}


//----------使用-----------

// 1.不传递参数使用
// MyComponent() 

// 2.传递参数使用:通过传递参数的方式 设置子组件中 messsage 的值
// MyComponent({message:'xxx'})
  • struct:自定义组件基于struct实现,struct + 自定义组件名 + {...}的组合构成自定义组件,不能有继承关系。对于struct的实例化,可以省略new。
  • @Component:@Component装饰器仅能装饰struct关键字声明的数据结构。
  • build()函数:build()函数用于定义自定义组件的声明式UI描述,自定义组件必须定义build()函数。
  • @Entry:@Entry装饰的自定义组件将作为UI页面的入口。在单个UI页面中,最多可以使用@Entry装饰一个自定义组件。
  • @Preview:如果想要单独预览组件,可以使用@Preview 进行装饰

1.2成员函数/变量

自定义组件除了必须要实现build()函数外,还可以定义其他的成员函数,以及成员变量

:::info 注意:

  1. 不支持静态函数、静态成员变量
  2. 成员函数、变量均为私有

:::

@Component
struct MyComponent {
  // 状态变量
  @State message:string=''
  // 成员变量-数据
  info:string = ''
  // 成员变量-函数
  sayHello=()=>{}
  
  // 成员函数
  sayHi(){
    
  }
  
  build(){
    // .... 描述 UI
  }
}

:::info

  1. 添加自定义组件
  1. 定义成员变量(普通变量、状态变量)
  2. 定义成员函数
  3. 调用函数,修改成员变量(普通变量、状态变量)
  1. 使用自定义组件
  1. 无参数调用
  2. 传递参数调用

:::

// HelloComponent.ets
@Component
export struct HelloComponent {
  // 成员变量
  info: string = '感觉自己闷闷哒'
  // 成员变量也可以是函数
  sayHello=()=>{}
  // 状态变量
  @State message: string = 'Hello, World!';

  // 成员函数
  sayHi() {
    console.log('你好呀')
  }

  build() {
    // HelloComponent自定义组件组合系统组件Row和Text
    Column() {
      Text(this.message)
      Text(this.info)
      Button('修改数据')
        .onClick(() => {
          this.info = '(*  ̄3)(ε ̄ *)'
          this.message = 'Hello,ArkTS'
          this.sayHi()
          this.sayHello()
        })

    }
  }
}


// 页面的.ets
import { HelloComponent } from './components/HelloComponent'

@Entry
@Component
struct CustomComponentDemo {
  build() {
    Column() {
      // 使用组件内部定义的初始值
      HelloComponent()
      // 使用传入的值,覆盖子组件的默认值
      HelloComponent({ info: '你好', message: 'ArkTS' })
      // 函数也可以传入
      HelloComponent({ sayHello(){ console.log('传入的逻辑') } })
    }
  }
}

1.3通用样式

自定义组件可以通过点语法的形式设置通用样式,通用事件

子组件()
  .width(100)
  .height(100)
  .backgroundColor(Color.Orange)
  .onClick(() => {
      console.log('外部添加的点击事件')
    })

:::info

  1. 添加自定义组件,随意设置内容
  2. 使用自定义组件,通过点语法设置通用样式

:::

@Component
struct MyComponent2 {
  build() {
    Button(`Hello World`)
  }
}

@Entry
@Component
struct MyComponent {
  build() {
    Row() {
      MyComponent2()
        .width(200)
        .height(300)
        .backgroundColor(Color.Red)
        .onClick(() => {
            console.log('外部添加的点击事件')
          })
    }
  }
}

:::info 说明

ArkUI给自定义组件设置样式时,相当于给MyComponent2套了一个不可见的容器组件,而这些样式是设置在容器组件上的,而非直接设置给MyComponent2的Button组件。通过渲染结果我们可以很清楚的看到,背景颜色红色并没有直接生效在Button上,而是生效在Button所处的开发者不可见的容器组件上。

:::

©著作权归作者所有,如需转载,请注明出处,否则将追究法律责任
标签
收藏
回复
举报
回复
    相关推荐