自定义构建函数

2024-01-18  本文已影响0人  家乡的蝈蝈

1、自定义构建函数

1.1、构建函数- @Builder

  如果你不想在直接抽象组件,ArkUI还提供了一种更轻量的UI元素复用机制 @Builder,可以将重复使用的UI元素抽象成一个方法,在 build 方法里调用。称之为自定义构建函数

1.1.1、全局自定义 @Builder function name () {}

  全局自定义函数指在struct外面的函数

@Builder
function getCellContent(leftTitle: string, rightValue: string) { // 全局自定义函数带function
  Row() {
    Row() {
      Text(leftTitle)
      Text(rightValue)
    }
    .width('100%')
    .justifyContent(FlexAlign.SpaceBetween)
    .padding({
      left: 15,
      right: 15
    })
    .borderRadius(8)
    .height(40)
    .backgroundColor(Color.White)
  }.padding({
    left: 10,
    right: 10
  })
}

在组件中使用

Column({space:10}) {
        getCellContent("时间", "2023-12-12")
        getCellContent("位置", "上海")
        getCellContent("爱好", "乒乓")
      }

全局自定义函数的问题
● 全局的自定义构建函数可以被整个应用获取(下一代可用-当前4.0暂不支持),不允许使用this和bind方法。
● 如果不涉及组件状态变化,建议使用全局的自定义构建方法。
● 补一句-如果数据是响应式的-此时该函数不会自动渲染-哪怕是全局自定义函数,不可被其他文件引用
将数据声明为State响应式数据

class CardClass {
  time: string = ""
  location: string = ""
  type: string = ""
}
@State formData: CardClass = {
    time: "2023-12-12",
    location: '回龙观',
    type: '漏油'
  }

传递数据,绑定为对应字段

Column({ space: 10 }) {
        getCellContent("异常时间", this.formData.time)
        getCellContent("异常位置", this.formData.location)
        getCellContent("异常类型", this.formData.type)
        Button("修改数据").onClick(() => {
          this.formData.location = "望京"
        })
      }
      .width('100%')

  我们发现,点击修饰是没有任何反应的,说明此时即使你用了State,但是此时的全局builder依然不更新

1.1.2、组件内定义- 语法 @Builder name () {}

@Entry
@Component
struct BuilderCase {
  @Builder
  getCellContent(leftTitle: string, rightValue: string) { // 组件内自定义函数不带function 
    }
}

调用

this.getCellContent("异常时间", this.formData.time)

  调用多了this,其他和全局属性一样,没有任何变化,此时我们发现修改数据依然没有任何变化
  注意: 我们刚刚传过去的是类型,string是一个基础数据类型,它是按值传递的,不具备响应式更新的特点
总结

1.2、参数传递

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

 1)、使用了string这种基础数据类型,即使它属于用State修饰的变量,也不会引起UI的变化
 2)、按引用传递参数时,传递的参数可为状态变量,且状态变量的改变会引起@Builder方法内的UI刷新。ArkUI提供$$作为按引用传递参数的范式。

ABuilder( $$ : 类型 );
函数名称( obj: 类型 );

 3)、也就是我们需要在builder中传入一个对象, 该对象使用$$(可使用其他字符)的符号来修饰,此时数据具备响应式了

@Entry
@Component
struct BuilderCase {
  @State formData: CardClass = {   // state修饰的状态变量
    time: "2023-12-12",
    location: '回龙观',
    type: '漏油'
  }
  @Builder
  getCellContent($$: CellParams) { // 传入一个对象,$$可以为任意字符
    Row() {
      Row() {
        Text($$.leftTitle)
        Text($$.rightValue)
      }
      .width('100%')
      .justifyContent(FlexAlign.SpaceBetween)
      .padding({
        left: 15,
        right: 15
      })
      .borderRadius(8)
      .height(40)
      .backgroundColor(Color.White)
    }.padding({
      left: 10,
      right: 10
    })
  }
  build() {
    Row() {
      Column() {
        Column({ space: 10 }) {
          this.getCellContent({ leftTitle: '异常时间', rightValue: this.formData.time }) // 传入一个对象,且有state修饰符修饰的变量
          this.getCellContent({ leftTitle: '异常位置', rightValue: this.formData.location }) // 传入一个对象,且有state修饰符修饰的变量
          this.getCellContent({ leftTitle: '异常类型', rightValue: this.formData.type })
        }
        .width('100%')
        Button("修改数据").onClick(() => {
          this.formData.location = "望京" // 修改state修改是的对象的属性,可以导致UI更新
        })
      }
      .width('100%')
    }
    .height('100%')
    .backgroundColor('#ccc')
  }
}

● 使用 @Builder 复用逻辑的时候,支持传参可以更灵活的渲染UI
● 参数可以使用状态数据,通过对象的方式传入 @Builder

上一篇下一篇

猜你喜欢

热点阅读