【鸿蒙开发教程】关于鸿蒙ArkUI中的builder装饰器的两个问题与实现

前言

根据研究机构 Counterpoint Research 发布的最新数据,2024 年第一季度,华为鸿蒙 HarmonyOS 在中国市场首次超越苹果 iOS。这意味着,鸿蒙 HarmonyOS 已成中国第二大操作系统。

随着鸿蒙的份额不断提升,我们很有必要学习一下鸿蒙开发。这边文章来跟大家聊一聊关于鸿蒙ArkUI中的builder装饰器的两个问题与实现

1. 首先, 要介绍一下什么是Builder装饰器

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

自定义组件内自定义构建函数

定义的语法:

@Builder MyBuilderFunction(){ ... }

使用方法:

this.MyBuilderFunction()

●允许在自定义组件内定义一个或多个@Builder方法,该方法被认为是该组件的私有、特殊类型的成员函数。
●自定义构建函数可以在所属组件的build方法和其他自定义构建函数中调用,但不允许在组件外调用。
●在自定义函数体中,this指代当前所属组件,组件的状态变量可以在自定义构建函数内访问。建议通过this访问自定义组件的状态变量而不是参数传递。

全局自定义构建函数

定义的语法:

@Builder function MyGlobalBuilderFunction(){ ... }

使用方法:

MyGlobalBuilderFunction()

●全局的自定义构建函数可以被整个应用获取,不允许使用this和bind方法。
●如果不涉及组件状态变化,建议使用全局的自定义构建方法。

2. 构建需求场景

1. 同一个全局构建函数, 如何使其触发不同的点击事件?
2. 全局构建函数, 如何更改外部组件的变量?

3.解决问题

显然, 在正常的全局构建函数中, 是没有办法做到以上两点的. 但是如果对于一个需要导出重复使用的组件来说, 在不使用@component装饰器的情况下, 有没有办法做到以上两点呢? 答案当然是可以的

3.1 同一个全局构建函数, 如何使其触发不同的点击事件?

对于这个问题, 其实很简单. 因为在builder构建函数内, 是可以传递参数的.
除了比较常见的简单类型的参数外, 其实还可以传递复杂类型的参数, 包括对象,或者函数等等.
在这里用得到方法就是回调函数.
我们可以把一个函数作为参数传入进去, 并且在点击时调用这个函数. 这样我们就可以在同一个构建函数上显示不同的点击功能

@Entry
@Component
struct chiqingsan {
  build() {
    Column({ space: 20 }) {
      mybutton(
        () => {
          // 配置不同的点击逻辑
          AlertDialog.show({
            message: "我是第一个按钮~"
          })
        }
      )
      mybutton(
        () => {
          AlertDialog.show({
            message: "我是第二个按钮~"
          })
        })
      mybutton(
        () => {
          AlertDialog.show({
            message: "我是第三个按钮~"
          })
        })
    }.width("100%").height("100%")
  }
}

@Builder
export function mybutton(fn?: () => void) {
  Button("按钮")
    .onClick(() => {
      fn()
    })
}

3.2 全局构建函数, 如何更改外部组件的变量?

在官网的 开发文档 中, 介绍了两种构建函数传值的方式, 一种是按值传递, 一种是引用传递. 这里我们用到的是引用传递.
在这里插入图片描述

但是需要注意的是, 在编辑器中使用开发文档中提供的语法是会直接报错的. 也就是说, 在本篇文章写下的当前(2024.04.21), 官网的文档是落后于编辑器版本的.
其正确的写法是:

// 1. 首先定义对象的结构类型
interface mytype {
  num: number
}

// 使用$$符来完成引用传值
@Builder
export function mybutton($$: mytype) {
  Button($$.num.toString())
}

这样我们就完成了这个需求的第一步, 当外部的值改变时, 构建函数所引用的值也会同步的重新渲染.
那我们是不是可以在内部直接对值进行修改呢?
答案是不行的, 当我们在构建函数内部对引用传递过来的值做改变时, 里立马报错.

// 1. 首先定义对象的结构类型
interface mytype {
  num: number
}

// 使用$$符来完成引用传值
@Builder
export function mybutton($$: mytype) {
  Button("按钮")
    .onClick(() => {
      $$.num++
    })
}

在这里插入图片描述

显然, 直接修改是不允许的. 这是鸿蒙ArkUI对开发所作出的限制.
那就没办法了吗? 不, 是有办法的. 既然我们不能直接去修改传过来的值, 那么间接的修改呢?结合第一个问题提到的回调函数, 我们对代码做一些修改

@Entry
@Component
struct chiqingsan {
  @State num1: number = 0

  build() {

    Column({ space: 20 }) {
      mybutton({
        num: this.num1, fn: () => {
          this.num1++
        }
      })
    }.width("100%").height("100%")
  }
}

// 1. 首先定义对象的结构类型
interface mytype {
  num: number
  fn: () => void
}

// 使用$$符来完成引用传值
@Builder
export function mybutton($$: mytype) {
  Button($$.num.toString())
    .onClick(() => {
      $$.fn()
    })
}

这样, 我们做到了在全局构建函数内部去影响到了外部的值. 实现的过程是:

1.创建好需要引用传值过来的数据结构, 使用$$引用传递来传值
2.在构建函数内部, 拿到引用传递过来的值, 这样就可以在外面值改变的时候, 构建函数内同步的进行更新
3.在点击事件内, 调用传递过来的回调函数
4.因为回调函数在外层, 所以可以直接对外部的变量进行修改. 这样就避免了在构建函数内部直接修改引用传递过来的值所造成的报错
5.外部的值发生改变, 引发构造函数内的值同步改变. 视图重新渲染

到此, 我们就完成了在全局构建函数, 去更改外部组件的变量,并且视图同步刷新

4.总结

其实, 在ArkUI的开发中, 官方是跟推荐使用@component组件去完成以上两个操作的.
以上案例, 只是我在使用全局builder的时候的一些奇思妙想, 并且对如何去实现的一些研究与记录. 前端框架茫茫多,还得慢慢学习啊

写在最后

总的来说,华为鸿蒙不再兼容安卓,对程序员来说是一个挑战,也是一个机会。随着鸿蒙的不断发展以及国家的大力支持,未来鸿蒙职位肯定会迎来一个大的爆发,只有积极应对变化,不断学习和提升自己,我们才能在这个变革的时代中立于不败之地。

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值