鸿蒙开发自定义构建函数&自定义组件【华为根技术】

举报
tea_year 发表于 2025/07/30 16:33:07 2025/07/30
【摘要】 @Builder装饰器:自定义构建函数https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/arkts-builder-V5ArkUI提供了一种轻量的UI元素复用机制@Builder,其内部UI结构固定,仅与使用方进行数据传递,开发者可以将重复使用的UI元素抽象成一个方法,在build方法里调用。为了简化语言,我们将...

@Builder装饰器:自定义构建函数

https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/arkts-builder-V5
ArkUI提供了一种轻量的UI元素复用机制@Builder,其内部UI结构固定,仅与使用方进行数据传递,开发者可以将重复使用的UI元素抽象成一个方法,在build方法里调用。
为了简化语言,我们将@Builder装饰的函数也称为“自定义构建函数”。
  1. 应用场景

@Builder私有自定义构建函数

  • 私有的在组件内部定义,前面不加function
  • 私有的自定义构建函数,调用时要加this
  • 私有的可以访问组件状态
@Component
struct Test{
@State a: string = ''
 
// 自定义构建函数
@Builder
//title为自定义函数名
//text为函数调用时传来的参数,参数可以有,也可以没有
title(text: string) {
  Row() {
   ...
  }
  .width('100%')
  .height(56)
}


 build(){
    Column(){
       Text('aaa')
       //调用自定义构建函数
       this.title()
    }
 }
}

@Builder全局自定义构建函数

  • 全局的在组件外部定义,前面必须加function
  • 全局的自定义构建函数,调用时不加this
  • 全局的不能访问组件状态
@Builder
function title(txt: string, content: string) {
  Row() {
    Text(txt)
    Text('-------')
    Text(`这个${content}也不一样`)
    Blank()
    Text("查看更多-----")
    Text(this.activeIndex.toString()) // 报错,不能访问组件的状态
  }
  .border({ width: 1, color: '#f00' })
  .width('100%')
}


@Entry
@Component
struct Test {
  @State activeIndex: number = 8
  build() {
    Column() {
      //调用全局的Builder
      title('1', '冰天')
    }
  }
}

创建自定义组件

https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V13/arkts-create-custom-components-V13
  1. 认识组件

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

  • 可组合:允许开发者组合使用系统组件、及其属性和方法。
  • 可重用:自定义组件可以被其他组件重用,并作为不同的实例在不同的父组件或容器中使用。
  • 数据驱动UI更新:通过状态变量的改变,来驱动UI的刷新。
  1. 创建自定义组件

子组件.ets

@Component
export struct ChildComponent {
  // @Prop message: string = ''  // 单向数据绑定
  // @Link message: string = ''  // 双向数据绑定
  
  build() {
    Text('改变message')
    .onClick(()=>{
       this.message = 'how are you'
    })
  }
}

父组件.ets

总结

声明: 下面提到的State是指父子组件传递的参数
  • @State接收参数
      如果用@State接收父组件的传参,当父组件的State改变时,子组件不会更新(同步)
  • @Prop 接收参数
      @Prop单向数据绑定
      @Prop装饰器用来接收父组件的传参,可以不定义初始值
      用@Prop接收的参数,在父组件的State改变时,子组件也会更新
      用@Prop接收的参数,在子组件修改后,子组件更新,但父组件不更新
  • @Link接收参数
      @Link 实现双向数据绑定
      父组件State修改,子组件会更新
      子组件State修改,父组件也会更新
      @Link不能初始值

传递多个参数,传复杂数据

父组件

import { TopBar } from "../common/TopBar"

//
/**
 *  TS的数据类型分两大类
 *   1. 基本数据类型  string number boolean ...
 *      name = 'bbbb'
 *   2. 引用数据类型  数组[]  对象{}
 *      arr = ['aaa','bbb']
 *      obj = {
 *        username: 'aaaa',
 *        desc: 'bbbb'
 *      }
 */
export interface StudentModel {
  name: string,
  age: number,
  gender: string
}
@Entry
@Component
export struct Rank {
  @State message: string = '热销榜'
  @State student: StudentModel = {
    name: '张三',
    age: 16,
    gender: '其他'
  }

  build() {
    Column() {
      Text("当前是榜单页")
      TopBar({
        title: this.message,
        color: '红色',
        stu: this.student
      })
    }
    .width('100%')
    .height('100%')
  }
}

子组件

import { StudentModel } from "../pages/Rank"

@Component
export struct TopBar {
  @Prop title: string
  @Prop color: string
  @Prop stu: StudentModel
  build() {
    Row() {
      Text("返回箭头").margin(10)
      Text(this.title)
      Blank()
      Text(this.color)
      Text(this.stu.name)
    }
    .width("100%")
    .height("40")
    .border({ width: 1, color: '#f00' })
    .backgroundColor(Color.Orange)
  }
}

@Provide和@Consume实现后代组件的双向绑定

  • @Provide装饰器可以向后代组件传递参数
  • @Consume装饰器接收祖先组件传递的参数
  • 二者实现的是数据的双向绑定,也就是祖先和后代任意一方修改数据,都能同步更新

案例代码

祖先组件
import { Child } from '../common/Child'

@Entry
@Component
struct Index {
  // @Provide装饰器可以向后代组件传递参数
  @Provide color: string = '祖先组件的红色'
  @Provide("student") a: string = '张三'
  build() {
    Column(){
      // Button("改变数据")
      //   .onClick(()=>{
      //     this.color = '新的绿色'
      //   })
      Text(this.color)
      Text("首页-父组件")
      Divider().color(Color.Red)
      Child()
    }
  }
}

子组件

import { GrandSon } from "./GrandSon"

@Component
export struct Child {
  build() {
    Column() {
      Text('这是子组件')
      GrandSon()
    }
    .width("100%")
    .height(350)
    .border({ width: 1, color: '#f00' })
  }
}
后代组件
@Component
export struct GrandSon {
  // @Consume装饰器接收祖先组件传递的参数
  @Consume color: string
  // 接收student, 同时可以给变量一个别名
  // 如果接收的数据和当前组件中的状态名冲突,就可以创建别名
  @Consume("student") name: string

  build() {
    Column() {
      Button("改变数据")
        .onClick(()=>{
          this.color = '新的绿色'
        })
      Text("这是孙组件")
      Text(this.color)
      Text(this.name)
    }
    .width('100%')
    .border({ width: 1, color: '#0f0' })
  }
}

把方法做为参数进入传递

@Entry
@Component
struct Del {
  @State message: string = '我是父组件的信息'

  show(){
    // AlertDialog.show({
    //   message: this.message
    // })
    console.log('aaaa')
  }

  build() {
    Row(){
        Text("父组件")
        Child({
          show: this.show
        })
    }

      .width(300)
      .height(160)
  }
}

@Component
struct Child {
  show: () => void = () => {
  };
  build() {
     Button("单击,会调用父组件的方法").onClick(()=>{
          this.show()
     })
  }
}

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。