【鸿蒙HarmonyOS开发笔记】组件编程技巧之使用@Builder装饰器实现UI结构复用

概述

当页面有多个相同的UI结构时,若每个都单独声明,同样会有大量重复的代码。为避免重复代码,可以将相同的UI结构提炼为一个自定义组件,完成UI结构的复用。

除此之外,ArkTS还提供了一种更轻量的UI结构复用机制@Builder方法,开发者可以将重复使用的UI元素抽象成一个@Builder方法,该方法可在build()方法中调用多次,以完成UI结构的复用。


语法说明

@Builder方法同样可以定义在组件内或者全局,具体语法如下

● 组件内

@Entry
@Component
struct BuilderPage {build() {Column() {Row({ space: 50 }) {//复用UI结构this.compButtonBuilder($r('app.media.icon_edit'), '编辑', () => console.log('编辑'))this.compButtonBuilder($r('app.media.icon_send'), '发送', () => console.log('发送'))}}.width('100%').height('100%').justifyContent(FlexAlign.Center)}//定义UI结构@Builder compButtonBuilder(icon: Resource, text: string, callback: () => void) {Button() {Row({ space: 10 }) {Image(icon).width(25).height(25)Text(text).fontColor(Color.White).fontSize(25)}}.width(120).height(50).onClick(callback)}
}

● 全局

@Entry
@Component
struct BuilderPage {build() {Column() {Row({ space: 50 }) {//复用UI结构globalButtonBuilder($r('app.media.icon_edit'), '编辑', () => console.log('编辑'))globalButtonBuilder($r('app.media.icon_send'), '发送', () => console.log('发送'))}}.width('100%').height('100%').justifyContent(FlexAlign.Center)}
}//定义UI结构
@Builder function globalButtonBuilder(icon: Resource, text: string, callback: () => void) {Button() {Row({ space: 10 }) {Image(icon).width(25).height(25)Text(text).fontColor(Color.White).fontSize(25)}}.width(120).height(50).onClick(callback)
}

注意

  1. 组件内的@Builder方法可通过this访问当前组件的属性和方法,而全局的@Builder方法则不能
  2. 组件内的@Builder方法只能用于当前组件,全局的@Builder方法导出(export)后,可用于整个应用。

@Builder方法参数传递规则

@Builder方法具有两种参数传递机制——按值传递按引用传递。当只有一个参数且参数为对象字面量时为按引用传递,其余情况均为按值传递。

按引用传递时,若传递的参数为状态变量,则状态变量的变化将会触发@Builder方法内部UI的刷新;按值传递时则不会。

@Entry
@Component
struct BuilderParameterPage {@State count: number = 0;build() {Column({ space: 50 }) {//按值传递valueTextBuilder(this.count)//按引用传递referenceTextBuilder({ count: this.count })Row({ space: 50 }) {Button('-1').onClick(() => {this.count--;})Button('+1').onClick(() => {this.count++;})}}.width('100%').height('100%').justifyContent(FlexAlign.Center)}
}@Builder function valueTextBuilder(count: number) {Text(`按值传递: ${count}`).fontSize(30).fontWeight(FontWeight.Bold)
}@Builder function referenceTextBuilder(obj: { count: number }) {Text(`按引用传递: ${obj.count}`).fontSize(30).fontWeight(FontWeight.Bold)
}

@Builder方法和自定义组件的区别

@Builder方法和自定义组件虽然都可以实现UI复用的效果,但是两者还是有着本质的区别的,其中最为显著的一个区别就是自定义组件可以定义自己的状态变量,而@Builder方法则不能。

以下案例中,每个待办事项的UI结构都相同,因此可考虑将其提炼为一个自定义组件或者@Builder方法,但是由于每个待办事项均有已完成未完成两种状态,因此需要为每个待办事项都定义一个状态变量,所以此时就只能使用自定义组件而不能使用@Builder方法。

在这里插入图片描述

总结

若复用的UI结构没有状态,推荐使用@Builder方法,否则使用自定义组件。


@BuilderParam

@BuilderParam用于装饰自定义组件(struct)中的属性,其装饰的属性可作为一个UI结构的占位符,待创建该组件时,可通过参数为其传入具体的内容。(其作用类似于Vue框架中的slot)。

例如

定义一个组件,使用@BuilderParam占位

@Component
struct Container {//@BuilderParam属性@BuilderParam content: () => voidbuild() {Column() {Text('其他内容') //其他内容this.content(); //占位符Button('其他内容') //其他内容}}
}

定义UI结构

@Builder function contentBuilder1() {...
}@Builder function contentBuilder2() {...
}@Builder function contentBuilder3() {...
}

组件创建时可传入不同的UI来填充

Container({ content: contentBuilder1 })Container({ content: contentBuilder2 })Container({ content: contentBuilder3 })

另外,如果一个组件中只定义了一个@BuilderParam属性,那么创建该组件时,也可直接通过"子组件"的方式传入具体的UI结构,例如

@Entry
@Component
struct BuilderParamPage {build() {Column({ space: 50 }) {//创建卡片组件(传参)Card({ content: imageBuilder })//创建卡片组件("子组件")Card() {Column({ space: 10 }) {Text('鸿蒙操作系统').fontSize(25).fontWeight(FontWeight.Bold)Text('鸿蒙操作系统是一款由华为公司开发的多设备统一操作系统,致力于实现无缝连接和协同工作。其采用分布式架构,支持多终端智能互联,提供高效、安全、流畅的用户体验。')}}}.width('100%').height('100%').justifyContent(FlexAlign.Center)}
}//卡片内容
@Builder function imageBuilder() {Column({ space: 10 }) {Image($r('app.media.img_harmony')).width(300).height(150)Text('鸿蒙操作系统')}
}//卡片组件
@Component
struct Card {@BuilderParam content: () => void; //@BuilderParam属性build() {Column() {this.content(); //占位符}.width('90%').padding(10).borderRadius(10).shadow({ radius: 20 })}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/752368.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

小白DB补全计划Day1-LeetCode:SQL基本操作select

前言:找工作(主人)的任务罢了 链接:1757. 可回收且低脂的产品 - 力扣(LeetCode) 584. 寻找用户推荐人 - 力扣(LeetCode) 来源:LeetCode 对DB篇的SQL章不太知道怎么写…

数学建模-估计出租车的总数

文章目录 1、随机抽取的号码在总体的排序 1、随机抽取的号码在总体的排序 10个号码从小到大重新排列 [ x 0 , x ] [x_0, x] [x0​,x] 区间内全部整数值 ~ 总体 x 1 , x 2 , … , x 10 总体的一个样本 x_1, x_2, … , x_{10} ~ 总体的一个样本 x1​,x2​,…,x10​ 总体的一个样…

mysql与redis数据测试

题目要求 1.新建一张user表,在表内插入10000条数据。 2.①通过jdbc查询这10000条数据,记录查询时间。 ②通过redis查询这10000条数据,记录查询时间。 3.再次查询这一万条数据,要求根据年龄进行排序,mysql和redis各实现…

【FPGA/IC】什么是模块化设计?

什么是模块化设计 FPGA/IC设计中根据模块层次的不同有两种基本的设计方法: 自下而上方法对设计进行逐次划分的过程是从基本单元出发的,设计树最末枝上的单元是已经设计好的基本单元,或者其他项目开发好的单元或者IP。该方法先对底层的功能块…

探索发布-订阅模式的深度奥秘-实现高效、解耦的系统通信

​🌈 个人主页:danci_ 🔥 系列专栏:《设计模式》 💪🏻 制定明确可量化的目标,坚持默默的做事。 🚀 转载自:探索设计模式的魅力:探索发布-订阅模式的深度奥秘-…

Jest:JavaScript的单元测试利器

🤍 前端开发工程师、技术日更博主、已过CET6 🍨 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 🕠 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 🍚 蓝桥云课签约作者、上架课程《Vue.js 和 E…

作品展示ETL

1、ETL 作业定义、作业导入、控件拖拽、执行、监控、稽核、告警、报告导出、定时设定 欧洲某国电信系统数据割接作业定义中文页面(作业顶层,可切英文,按F1弹当前页面帮助) 涉及文件拆分、文件到mysql、库到库、数据清洗、数据转…

Vue mqtt 附在线mqtt客户端地址 + 完整示例

mqtt:轻量级物联网消息推送协议。 目录 一、介绍 1、官方文档 1)npm网 2) 中文网 MQTT中文网_MQTT 物联网接入平台-MQTT.CN 2、官方示例 二、准备工作 1、安装依赖包 2、示例版本 三、使用步骤 1、在单页面引入 mqtt 四、完整示例 tips 一、介…

渐开线花键环规的几种加工方法

小伙伴们大家好,今天咱们聊一聊渐开线花键环规的几种加工方法。 渐开线花键环规是在汽车、摩托车以及机械制造工业应用非常广泛的一种检测量具。它属于是一种内花键齿轮,其精度和表面粗糙度要求都比较高。采用的加工方法也比较多,下面详细看…

【爬虫逆向】Python逆向采集猫眼电影票房数据

进行数据抓包,因为这个网站有数据加密 !pip install jsonpathCollecting jsonpathDownloading jsonpath-0.82.2.tar.gz (10 kB)Preparing metadata (setup.py) ... done Building wheels for collected packages: jsonpathBuilding wheel for jsonpath (setup.py) .…

Android VINF

周末搞这玩意欲仙欲死,没办法只有看看。VINTF是供应商接口对象(VINTF 对象),准确的说,这个是属于兼容性矩阵概念。。。有点想起了以前看过的一个电影,异次元杀阵。。。下面是谷歌官方的图。 本质上其实就是…

C++之类和对象(3)

目录 1. 再谈构造函数 1.1 构造函数体赋值 1.2 初始化列表 1.3 explicit 2. static成员 2.1 概念 3. 友元 3.1 友元函数 3.2 友元类 4. 内部类 5. 匿名对象 6. 拷贝对象时编译器做出的优化 1. 再谈构造函数 1.1 构造函数体赋值 class Date { public:Date(int year2024…

Helm Chart部署最简SpringBoot到K8S(AWS EKS版)

目标 这里假设,我们已经基本会使用k8s的kubectl命令进行部署了,也已经会自己打docker镜像推送到AWS ECR上面去了。而且,已经在云上准备好了AWS ECR镜像库和AWS EKS的k8s集群了。 这个前提上面,我们今天使用Helm Chart项目准备k8s…

数据结构试卷第九套

1.时间复杂度 2.树,森林,二叉树的转换 2.1树转二叉树 给所有的兄弟节点之间加一条连线;去线,只保留当前根节点与第一个叶子节点的连线,删除它与其他节点之间的连线;然后根据左孩子右兄弟进行调整&#xf…

个人网站制作 Part 11 添加用户权限管理 | Web开发项目

文章目录 👩‍💻 基础Web开发练手项目系列:个人网站制作🚀 添加用户权限管理🔨使用Passport.js🔧步骤 1: 修改Passport本地策略 🔨修改用户模型🔧步骤 2: 修改用户模型 &#x1f528…

医学数据分析中缺失值的处理方法

医学数据分析中缺失值的处理方法 (为了更好的展示,在和鲸社区使用代码进行展示) 医学数据分析中,缺失值是不可避免的问题。缺失值的存在会影响数据的完整性和准确性,进而影响分析结果的可靠性。因此,在进…

中创ET4410台式电桥固件升级工具(修复了列表扫描的BUG)

中创ET4410台式LCR数字电桥固件升级工具和最新版固件(修复了列表扫描的BUG) 中创ET4410 台式LCR数字电桥 简单开箱测评:https://blog.zeruns.tech/archives/763.html 之前买的中创ET4410台式LCR数字电桥固件有BUG(胜利的VC4090C…

FREERTOS中断配置和临界段

本文基础内容参考的是正点原子的FREERTOS课程。 这是基于HAL库的 正点原子手把手教你学FreeRTOS实时系统 这是基于标准库的 正点原子FreeRTOS手把手教学-基于STM32 回顾STM32的中断 什么是中断? 中断优先级分组设置 Freertos中断分组 Freertos就是用的最后一种&…

redis学习-redis介绍

目录 1.redis介绍 2.redis常用命令(可以在官网的命令中查看redis的所有命令) 2.1终端命令 2.2 redis通用命令 2.3五大基本类型的命令以及特殊情况分析 (导航) 3.事务 4. redis实现消息订阅 5. redis的两种持久化策略 …

KubeSphere集群安装-nfs分布式文件共享-对接Harbor-对接阿里云镜像仓库-遇到踩坑记录

KubeSphere安装和使用集群版 官网:https://www.kubesphere.io/zh/ 使用 KubeKey 内置 HAproxy 创建高可用集群:https://www.kubesphere.io/zh/docs/v3.3/installing-on-linux/high-availability-configurations/internal-ha-configuration/ 特别注意 安装前注意必须把当前使…