鸿蒙应用开发之@Builder自定义构建函数:值传递与引用传递与UI更新

52 阅读3分钟

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

@Builder装饰的函数称为自定义构建函数,它是一种轻量化 UI 复用机制,它允许开发者将重复使用的 UI 元素抽象为函数,这些函数可以在 build 函数中被调用以实现 UI 复用。

自定义构建函数根据定义的位置不同分为私有自定义函数全局自定义函数

私有自定义构建函数

私有自定义构建函数定义在@Component组件内,属于该组件私有的,只能在该组件内build函数或者其他自定义构建函数中调用。

@Component
struct MyComponent {
  build() {
    Column() {
      this.myBuilder()
    }
  }

  @Builder
  myBuilder() {
    Text("私有@Builder")
  }
}

@Entry
@Component
struct Index {
  build() {
    Column({ space: 10 }) {
      MyComponent()
    }
    .width("100%")
    .height("100%")
  }
}

全局自定义构建函数

全局自定义函数定义在@Component组件外,可以在其他自定义函数或者其他自定义组件中调用。

@Builder
function myBuilder() {
  Text("全局@Builder")
}

@Entry
@Component
struct Index {
  build() {
    Column({ space: 10 }) {
      myBuilder()
    }
    .width("100%")
    .height("100%")
  }
}

@Builder与@Component的区别

经过上面的描述可能会发现@Component和@Builder都可以用于UI复用,他们的区别如下:

  • @Builder:纯UI逻辑复用,无独立状态管理与生命周期,必须通过参数传递的方式与调用方完成数据交互。
  • @Component:完整组件封装,拥有独立状态管理与生命周期。

自定义构建函数参数传递规则

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

  • 参数的类型必须与参数声明的类型一致,不允许undefined、null和返回undefined、null的表达式。
  • @Builder装饰的函数内部,不允许改变参数值。
  • 只有当传入一个参数且该参数直接传入对象字面量时,才会按引用传递,其他传递方式均为按值传递。

按值传递参数

定义一个全局自定义构建函数textBuilder(text: string),参数只有一个且不是字面量对象,所以按照值传递。

@Builder
function textBuilder(text: string) {
  Text("Hello,"+text).fontSize(30)
}

调用@Builder装饰的函数默认按值传递。当传递的参数为状态变量时,状态变量的改变不会引起@Builder函数内的UI刷新


@Entry
@Component
struct Index {
  @State text: string = 'World'

  build() {
    Column() {
      textBuilder(this.text)
      Button("修改text").onClick(() => {
        //修改状态变量,不会引用@Builder函数中UI的更新
        this.text = "ArkUI"
      })
    }
  }
}

如下图,经测试状态变量的改变不会引起@Builder函数内UI刷新

在这里插入图片描述

按引用传递参数

定义一个@Builder自定义构建函数,参数为自定义对象类型。

class Params {
  text: string = ''
}

@Builder
function textBuilder(params: Params) {
  Text(`Hello, ${params.text}`).fontSize(30)
}

调用按引用传递参数时,传递的参数可为状态变量,且状态变量的改变会引起@Builder函数内的UI刷新。

@Entry
@Component
struct Index {
  @State text: string = 'World'

  build() {
    Column() {
      textBuilder({
        text: this.text
      })
      Button("修改text").onClick(() => {
        //修改状态变量,不会引用@Builder函数中UI的更新
        this.text = "ArkUI"
      })
    }
  }
}

预览效果如下图所示:

在这里插入图片描述

限制条件

  • @Builder自定义函数内部不允许修改参数值,否则框架会抛出运行时异常。
  • @Builder自定义构建函数存在两个或两个以上的参数时,即使通过对象字面量形式传递,值的改变也不会触发UI刷新。

示例1:在@Builder中修改参数值

class Params {
  text: string = ''
}

@Builder
function textBuilder(params: Params) {
  Text(`Hello, ${params.text}`).fontSize(30)
    .onClick(() => {
      params.text = "哈哈哈"	//【错误】,禁止改参数的值
    })
}

如下图所示,出现预览错误

在这里插入图片描述

示例2:在@Builder中接收两个参数,不会触发UI更新。

import { promptAction } from "@kit.ArkUI"

class Params {
  text: string = ''
}

@Builder
function textBuilder(params: Params,num:number) {
  Column(){
    Text(`Hello, ${params.text}`).fontSize(30)
      .onClick(() => {
        params.text = "哈哈哈"
      })

    Text(`${num}`)
  }

}

@Entry
@Component
struct Index {
  @State text: string = 'World'

  build() {
    Column() {
      textBuilder({
        text: this.text
      },100)
      Button("修改text").onClick(() => {
        //修改状态变量,不会引用@Builder函数中UI的更新
        this.text = "ArkUI"
      })
    }
  }
}

如下图,当@Builder接收2个参数时,UI更新不生效。

在这里插入图片描述

对鸿蒙感兴趣的同学,免费考取鸿蒙开发者认证