当前位置: 首页 > news >正文

鸿蒙开发:wrapBuilder来封装全局@Builder

前言

本文代码案例基于Api13。

@Builder装饰器,可以把build函数中的组件代码,单独的抽取出来,虽然简化了build函数,实现了组件之间的复用,但是代码还是在整个UI视图内,如下案例所示:

@Entry
@Component
struct Index {
  @Builder
  TextView(text: string) {
    Text(text)
  }

  build() {
    Column() {
      this.TextView("测试数据1")
      this.TextView("测试数据2")
    }
    .height('100%')
    .width('100%')
    .justifyContent(FlexAlign.Center)
  }
}

只能说,在同一个UI视图中,实现了组件复用,简化了代码,但是,如果有很多个页面共用一个组件呢?还好,@Builder装饰器支持全局定义,这个在以往的文章中有过概述,可以把共用的组件抽取到一个全局文件中。

@Builder
export function TextView(text: string) {
  Text(text)
}

在需要的地方直接调用即可。

import { TextView } from './Views'

@Entry
@Component
struct Index {

  build() {
    Column() {
     TextView("测试数据1")
     TextView("测试数据2")
    }
    .height('100%')
    .width('100%')
    .justifyContent(FlexAlign.Center)
  }
}

哎,回过头来,我们发现,@Builder装饰器可局部可全局,已经满足了需求了啊,还要wrapBuilder干什么?先别着急,我们先看下这几个场景:

1、有一个自定义Dialog弹窗,需要接收从外部传递UI视图过来,请问,如何把组件传递过去?

2、有一个封装的网络库,其中有一个功能是请求加载Loading,由于每个项目的Loading不同,这个Loading组件视图需要单独传递,如何传递?

怎么能把外部定义的UI组件,传递给需要的地方呢?这些需要的地方可不是struct修饰的,大家想想看,能直接传递吗?

再看一个案例,虽然说,我们可以定义全局的@Builder装饰器,然而当我组合成数组后,却无法进行调用,如下代码:

import { TextView } from './Views';


let builderArr: Function[] = [TextView]


@Entry
@Component
struct Index {
  
  build() {
    Column() {

      ForEach(builderArr, (item: Function) => {
        item()
      })

    }
    .height('100%')
    .width('100%')
    .justifyContent(FlexAlign.Center)
  }
}

直接报错:

'item()' does not comply with the UI component syntax. <ArkTSCheck>

为了解决以上的问题,鸿蒙引入wrapBuilder作为全局@Builder封装函数,返回WrappedBuilder对象,以实现全局@Builder可以进行赋值和传递。

如何使用

wrapBuilder是一个模板函数,返回一个WrappedBuilder对象。

declare function wrapBuilder< Args extends Object[]>(builder: (...args: Args) => void): WrappedBuilder;

声明变量

let builderVar: WrappedBuilder<[string, number]> = wrapBuilder(MyBuilder)

简单案例:

import { TextView } from './Views'

@Entry
@Component
struct Index {
  textView: WrappedBuilder<[string]> = wrapBuilder(TextView)

  build() {
    Column() {
      this.textView.builder("测试数据")
    }
    .height('100%')
    .width('100%')
    .justifyContent(FlexAlign.Center)
  }
}

当然了,也可以直接在定义组件的地方进行声明变量。

@Builder
function TextView(test: string) {
  Text(test)
}

export let textView: WrappedBuilder<[string]> = wrapBuilder(TextView)

调用:

import { textView } from './Views'

@Entry
@Component
struct Index {
  build() {
    Column() {
      textView.builder("测试数据")
    }
    .height('100%')
    .width('100%')
    .justifyContent(FlexAlign.Center)
  }
}

传递数据

其实在上边的案例中,已经是传递参数的案例,遵循着,接收什么类型就传递什么类型。

比如接收的是string类型。

let textView: WrappedBuilder<[string]> = wrapBuilder(TextView)

比如接收两个参数,一个是string,一个是number。

@Builder
function TextView(test: string,num:number) {
  Text(test)
}

export let textView: WrappedBuilder<[string,number]> = wrapBuilder(TextView)

如果传递参数过多,可以通过对象,数组,集合等形式传递,下面举一个引用类型传递:

定义对象

export class TestBean {
  testData?: string = "测试数据"
}

创建全局组件

import { TestBean } from "./TestBean"

@Builder
function TextView(test: TestBean) {
  Text(test.testData)
}

export let textView: WrappedBuilder<[TestBean]> = wrapBuilder(TextView)

组件调用

import { TestBean } from './TestBean';
import { textView } from './Views'

@Entry
@Component
struct Index {
  @State test: TestBean = new TestBean();

  build() {
    Column() {
      textView.builder({ testData: this.test.testData })
      Button("点击").onClick(() => {
        this.test.testData = "改变数据"
      })
    }
    .height('100%')
    .width('100%')
    .justifyContent(FlexAlign.Center)
  }
}

相关总结

首先第一点,在同一个UI组件内,同一个wrapBuilder只能初始化一次,第二点就是WrappedBuilder对象的builder属性方法只能在struct内部使用。

如何接收一个外部传来的UI组件呢,很是简单,只需要接收一个WrappedBuilder<[Object]>即可,简单案例如下:

export class ViewUtils {
  view?: WrappedBuilder<[Object]>

  setView(view: WrappedBuilder<[Object]>) {
    this.view = view
  }

  getView(): WrappedBuilder<[Object]> | undefined {
    return this.view
  }
}

相关文章:

  • 企业级Python后端数据库使用指南(简略版)
  • 13天 -- Redis 中如何实现分布式锁? Redis 的 Red Lock 是什么?你了解吗? Redis 实现分布式锁时可能遇到的问题有哪些?
  • fastjson1.2.24 CVE-2017-18349 漏洞复现
  • 【pytest框架源码分析二】pluggy源码分析之add_hookspecs和register
  • Golang的性能分析指标解读
  • 如何解决跨域请求的问题(CORS)?
  • 张岳教授:语言模型推理与泛化研究 | ICLR 2025 特邀报告与团队专场
  • CPU负载高告警问题的定位与优化建议
  • 《OpenCV》—— dlib库(性别年龄预测)
  • C++中unique_ptr的实现
  • Markdown HTML 图像语法
  • Docker 学习(二)——私有仓库搭建
  • C语言数组
  • 经典内存泄漏问题
  • SQL Server2022版+SSMS安装教程(保姆级)
  • 【记录】环境报错问题:Error Get “https://registry-1.docker.io/v2/“
  • IP-----BGP协议
  • C# Unity 唐老狮 No.5 模拟面试题
  • Spring 源码硬核解析系列专题(扩展篇):Spring Batch 的恢复机制源码解析
  • LeetCode hot 100—合并两个有序链表
  • wordpress 切换中文/优化服务
  • 网站建设公司哪家好/seo排名第一的企业
  • 云服务器可以做图片外链网站吗/网络营销策划书论文
  • 网站设计制作公司推荐/网站查询工具seo
  • 交做网贷的网站/平台代运营是什么意思
  • 计算机网站开发论文参考文献/营销型企业网站建设步骤