【最新鸿蒙应用开发】——鸿蒙中的“Slot插槽”?@BuilderParam

news2024/12/28 19:40:12

构建函数-@BuilderParam 传递 UI

1. 引言

@BuilderParam 该装饰器用于声明任意UI描述的一个元素,类似slot占位符。 简而言之:就是自定义组件允许外部传递 UI

@Entry
@Component
struct Index {
  build() {
    Column({ space: 15 }) {
      SonCom() {
        // 直接传递进来(尾随闭包)
        Button('传入的结构')
          .onClick(() => {
            AlertDialog.show({ message: '点了 Button' })
          })
      }
    }
  }
}

2. 单个@BuilderParam参数

首先来看看单个的情况:

使用尾随闭包的方式传入:

  • 组件内有且仅有一个使用 @BuilderParam 装饰的属性,即可使用尾随闭包
  • 内容直接在 {} 传入即可 注意:
  • 此场景下自定义组件不支持使用通用属性。
@Component
struct SonCom {
  // 由外部传入 UI
  @BuilderParam ContentBuilder: () => void = this.defaultBuilder
​
  // 设置默认 的 Builder,避免外部不传入
  @Builder
  defaultBuilder() {
    Text('默认的内容')
  }
​
  build() {
    Column() {
      this.ContentBuilder()
    }
    .width(300)
    .height(200)
    .border({ width: .5 })
  }
}
​
@Entry
@Component
struct Index {
  build() {
    Column({ space: 15 }) {
      SonCom() {
        // 直接传递进来
        Button('传入的结构')
          .onClick(() => {
            AlertDialog.show({ message: '点了 Button' })
          })
      }
    }
  }
}

3. 多个@BuilderParam 参数

子组件有多个BuilderParam,必须通过参数的方式来传入

核心步骤:

  1. 自定义组件-定义: 添加多个 @BuilderParam ,并定义默认值

  2. 自定义组件-使用 通过参数的形式传入多个 Builder,比如这里的 SonCom({ titleBuilder: this.fTitleBuilder, contentBuilder: this.fContentBuilder })

需求:

  • 调整 卡片自定义组件,支持传入 UI PanelComp(){ // 此处传入 }

思路:

  • 直接大括号(尾随闭包)传入只需要设置一个BuilderParam即可:

@Component
struct PanelComp {
  title: string = ''
  more: string = ''
  @BuilderParam contentBuilder: () => void = this.defaultContentBuilder
  clickHandler: () => void = () => {
    AlertDialog.show({ message: '默认提示' })
  }
​
  @Builder
  defaultContentBuilder() {
    Text('默认的内容~')
  }
​
  build() {
    Column() {
      Row() {
        Text(this.title)
          .layoutWeight(1)
          .fontWeight(600)
        Row() {
          Text(this.more)
            .fontSize(14)
            .fontColor('#666666')
            .onClick(() => {
              this.clickHandler()
            })
          Image('/common/day08-10/ic_public_arrow_right.svg')
            .width(16)
            .fillColor('#666666')
        }
      }
      .padding(10)
​
      Row() {
        this.contentBuilder()
      }
      .height(100)
    }
    .borderRadius(12)
    .backgroundColor('#fff')
  }
}
​
@Entry
@Component
struct Index {
  build() {
    Column({ space: 15 }) {
      PanelComp({
        title: '评价(2000+)', more: '好评率98%', clickHandler() {
          console.log('传入的逻辑')
        }
      }) {
        Text('传入的标题')
          .fontSize(20)
          .fontWeight(600)
          .fontColor(Color.White)
          .backgroundColor(Color.Blue)
          .padding(10)
      }
​
      Row({ space: 15 }) {
        PanelComp({ title: '推荐', more: '查看全部' })
          .layoutWeight(1)
​
        PanelComp({ title: '体验', more: '4 条测评' })
          .layoutWeight(1)
      }
​
    }
    .height('100%')
    .padding(15)
    .backgroundColor('#f5f5f5')
  }
}

4. 使用场景

这里简单举例两个关于我项目中适合使用的场景:


4.1. 任务列表页面

  • 自定义插槽

@Preview
@Component
struct HmToggleCard {
  title: string = "测试"
  @State
  toggleCard: boolean = true // 默认是展开的
  @BuilderParam
  CardContent: () => void
  build() {
    Column() {
      Row() {
        Text(this.title)
          .fontSize(16)
          .fontColor($r('app.color.text_primary'))
          .fontWeight(600)
        Image(this.toggleCard ? $r("app.media.ic_btn_cut") :
        $r("app.media.ic_btn_add"))
          .width(24)
          .height(24)
          .onClick(() => {
            animateTo({ duration: 300 }, () => {
              this.toggleCard = !this.toggleCard
            })
​
          })
      }
      .width('100%')
      .justifyContent(FlexAlign.SpaceBetween)
      .height(50)
​
      // 放置传入的内容
      if(this.CardContent && this.toggleCard) {
        this.CardContent()
      }
    }
    .padding({
      left: 19.5,
      right: 19.5,
      bottom: 18.5
    })
    .margin({
      left: 15,
      right: 15,
      top: 15
    })
    .backgroundColor($r('app.color.white'))
    .borderRadius(10)
  }
}
​
export  { HmToggleCard }


  • 页面中进行复用的主要代码:

build() {
  Column() {
    HmNavBar({ title: '任务详情' })
    Scroll(this.scroll) {
      // Scroll里面只能有一个组件
      Column() {
        HmToggleCard({ title: '基本信息' }) {
          this.getBaseContent()
        }
​
        HmToggleCard({ title: '车辆信息' }) {
          this.getTransLineContent()
        }
​
        HmToggleCard({ title: '司机信息' }) {
          this.getDriverContent()
        }
​
        if (this.taskDetailData.exceptionList?.length > 0) {
          HmToggleCard({ title: '异常信息' }) {
            this.getExceptionContent()
          }
        }
​
        if (this.taskDetailData.status === TaskTypeEnum.Waiting ||
          this.taskDetailData.status === TaskTypeEnum.Delivered ||
          this.taskDetailData.status === TaskTypeEnum.Finish
        ) {
          HmToggleCard({ title: '提货信息' }) {
            this.getPickUpContent()
          }
        }
​
​
        if (this.taskDetailData.status === TaskTypeEnum.Line ||
          this.taskDetailData.status === TaskTypeEnum.Delivered
          || this.taskDetailData.status === TaskTypeEnum.Finish
        ) {
          HmToggleCard({ title: '交货信息' }) {
            this.getDeliverContent()
          }
        }
​
      }
      .padding({
        bottom: 130
      })
    }
​
    if (this.taskDetailData.status !== TaskTypeEnum.Finish) {
      // 只有在非完成情况下 才显示底部按钮
      this.getBottomBtn()
    }
  }.backgroundColor($r('app.color.background_page'))
  .height('100%')
}

4.2. 设置页面

  • 自定义插槽

@Component
export struct MkCell {
  @Prop label: string = ''
  @Prop value: string = ''
  @Prop icon: ResourceStr = $r('app.media.ic_public_right')
  @Prop hasBorder: boolean = true
​
  @Builder
  DefaultLabelBuilder() {
    Text(this.label)
      .fontSize(14)
      .fontColor($r('app.color.black'))
  }
​
  @Builder
  DefaultIconBuilder() {
    Image(this.icon)
      .width(20)
      .aspectRatio(1)
      .fillColor($r('app.color.gray'))
  }
​
  @BuilderParam customLabel: () => void = this.DefaultLabelBuilder
  @BuilderParam customIcon: () => void = this.DefaultIconBuilder
​
  build() {
    Row({ space: 8 }) {
      this.customLabel()
      Blank()
      if (this.value) {
        Text(this.value)
          .fontSize(14)
          .fontColor($r('app.color.gray'))
      }
      this.customIcon()
    }
    .width('100%')
    .constraintSize({ minHeight: 50 })
    .border({ width: { bottom: this.hasBorder ? 0.6 : 0 }, color: $r('app.color.under') })
  }
}
​
​
@Component
export struct MkCellGroup {
  @Builder
  DefaultBuilder() {
  }
​
  @BuilderParam default: () => void = this.DefaultBuilder
​
  build() {
    Column() {
      this.default()
    }
    .border({
      width: { top: 0.6, bottom: 0.6 },
      color: $r('app.color.under')
    })
    .padding({ left: 16, right: 16 })
    .backgroundColor($r('app.color.white'))
  }
}
  • 页面中进行复用的主要代码:

  build() {
    Column() {
      MkNavbar({ title: '设置' })
      Column({ space: 8 }) {
        MkCellGroup() {
          // 尾随闭包,MkCellGroup中只有一个 BuilderParam 即可使用尾随闭包
          // 多个 BuilderParam 需要用{}进行传递
          MkCell({
            hasBorder: false, customLabel: () => {
              this.ProfileBuilder()
            }
          })
​
        }
​
          MkCellGroup() {
            MkCell({ label: '收货地址管理' })
            MkCell({ label: '账号安全' })
            MkCell({ label: '消息设置' })
            MkCell({ label: '隐私设置' })
            MkCell({ label: '通用设置', hasBorder: false })
          }
​
          MkCellGroup() {
            MkCell({ label: '退出登录', hasBorder: false })
              .onClick(() => {
                auth.removeUser()
                router.back()
              })
          }
      }
    }
    .width('100%')
    .height('100%')
    .backgroundColor($r('app.color.under'))
  }

5.总结

当开发者创建了自定义组件,并想对该组件添加特定功能时,例如在自定义组件中添加一个点击跳转操作。若直接在组件内嵌入事件方法,将会导致所有引入该自定义组件的地方均增加了该功能。为解决此问题,ArkUI引入了@BuilderParam装饰器,@BuilderParam用来装饰指向@Builder方法的变量(@BuilderParam是用来承接@Builder函数的),开发者可在初始化自定义组件时对此属性进行赋值,为自定义组件增加特定的功能。该装饰器用于声明任意UI描述的一个元素,类似slot占位符。

1. 使用尾随闭包的方式传入:(开发者可以将尾随闭包内的内容看做@Builder装饰的函数传给@BuilderParam)

●组件内有且仅有一个使用 @BuilderParam 装饰的属性,即可使用尾随闭包。

●在初始化自定义组件时,组件后紧跟一个大括号“{}”形成尾随闭包场景。

注意:

●此场景下自定义组件不支持使用通用属性。

2. 多个@BuilderParam(无法使用尾随闭包)

需注意this指向正确。

以下示例中,Parent组件在调用this.componentBuilder()时,this指向其所属组件,即“Parent”。@Builder componentBuilder()通过this.componentBuilder的形式传给子组件@BuilderParam customBuilderParam,this指向在Child的label,即“Child”。@Builder componentBuilder()通过():void=>{this.componentBuilder()}的形式传给子组件@BuilderParam customChangeThisBuilderParam,因为箭头函数的this指向的是宿主对象,所以label的值为“Parent”。

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

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

相关文章

《大数据分析》期末考试整理

一、单项选择题(1*9) 1.大数据发展历程:出现阶段、热门阶段和应用阶段 P2 2.大数据影响 P3 1)大数据对科学活动的影响 2)大数据对思维方式的影响 3)大数据对社会发展的影响 4)大数…

昂科烧录器支持Prolific旺玖科技的电力监控芯片PL7413C1FIG

芯片烧录行业领导者-昂科技术近日发布最新的烧录软件更新及新增支持的芯片型号列表,其中Prolific旺玖科技的高度集成的电力监控芯片PL7413C1FIG已经被昂科的通用烧录平台AP8000所支持。 PL7413C1FIG是一款高度集成的电力监控芯片,用于测量电力使用情况的…

vue-饼形图-详细

显示效果 代码 <template> <div style"height: 350px;"> <div :class"className" :style"{height:height,width:width}"></div> </div> </template> <script> import * as echarts from echarts; req…

Typora实现设置代码块默认语言_亲测有效(AutoHotKey方式和修改配置文件)

Typora实现设置代码块默认语言&#xff08;AutoHotKey方式和修改配置文件&#xff09; 前言&#xff0c;需求使用AutoHotKey热键脚本【最简单方便】实现步骤建议 最终效果其他方法自定义Typora代码块快捷键设置。应对ctrlshiftk快捷键被其他占用的情况。 前言&#xff0c;需求 …

07--Zabbix监控告警

前言&#xff1a;和普米一样运维必会的技能&#xff0c;这里总结一下&#xff0c;适用范围非常广泛&#xff0c;有图形化界面&#xff0c;能帮助运维极快确定问题所在&#xff0c;这里记录下概念和基础操作。 1、zabbix简介 Zabbix是一个基于 Web 界面的企业级开源解决方案&a…

厂里资讯之自媒体文章自动审核

自媒体文章-自动审核 1)自媒体文章自动审核流程 1 自媒体端发布文章后&#xff0c;开始审核文章 2 审核的主要是审核文章的内容&#xff08;文本内容和图片&#xff09; 3 借助第三方提供的接口审核文本 4 借助第三方提供的接口审核图片&#xff0c;由于图片存储到minIO中&…

高速信号——NRZ,PAM4调制技术

1&#xff1a;码元 了解调制技术需要引出“码元”的概念。 一个码元就是一个脉冲信号&#xff0c;即一个最小信号周期内的信号&#xff0c;我们都能够理解&#xff0c;最简单的电路&#xff0c;以高电平代表1&#xff0c;低电平代表0&#xff0c;一个代表1或者0的信号&#x…

Linux基础I/O之文件描述符fd 重定向(上)

目录 一、预备知识 二、C语言中的文件接口 三、系统调用中的文件接口 一、预备知识 首先我们要明确的一个观点是 --- 文件 内容 属性。而且我们之前也还将过一个概念&#xff0c;那就是Linux下一切皆文件。 内容是数据&#xff0c;属性也是数据 --- 那么也就是说我…

t265 jetpack 6 px4 ros2

Ubuntu22.04 realsenseSDK2和ROS2Wrapper安装方法,包含T265版本踩坑问题_ros2 realsense-CSDN博客 210 git clone https://github.com/IntelRealSense/librealsense.git 212 git branch 215 git tag 218 git checkout v2.51.1 219 git branch 265 git clone https://…

C语言---------深入理解指针

目录 一、字符指针 二、指针数组&#xff1a; 三、数组指针&#xff1a; 1、定义&#xff1a; 2、&数组名和数组名区别&#xff1a; 3、数组指针的使用&#xff1a; 四、数组参数&#xff0c;指针参数&#xff1a; 1、一维数组传参&#xff1a; 2、二维数组传参&am…

基于springboot的大学计算机基础网络教学系统

文章目录 项目介绍主要功能截图:部分代码展示设计总结项目获取方式🍅 作者主页:超级无敌暴龙战士塔塔开 🍅 简介:Java领域优质创作者🏆、 简历模板、学习资料、面试题库【关注我,都给你】 🍅文末获取源码联系🍅 项目介绍 基于springboot的大学计算机基础网络教学…

opencv-python(十)

绘制直线 cv2.line(img, pt1, pt2, color, thickness1, lineTypeLINE_8) 上述代码可以从pt1点绘一条线到pt2点。 img&#xff1a;绘图对象 pt1&#xff1a;线段的起点&#xff0c;画布的左上角坐标是(0, 0) pt2&#xff1a;线段的终端 color&#xff1a;&#xff08;B&…

记录一次root过程

设备: Redmi k40s 第一步&#xff0c; 解锁BL&#xff08;会重置手机系统&#xff01;&#xff01;&#xff01;所有数据都会没有&#xff01;&#xff01;&#xff01;&#xff09; 由于更新了澎湃OS系统, 解锁BL很麻烦, 需要社区5级以上还要答题。 但是&#xff0c;这个手机…

React+TS前台项目实战(十)-- 全局常用组件CopyText封装

文章目录 前言CopyText组件1. 功能分析2. 代码详细注释3. 使用方式4. 效果展示 总结 前言 今天这篇主要讲项目常用复制文本组件封装&#xff0c;这个组件是一个用于拷贝文本的 React 组件&#xff0c;它提供了拷贝&#xff0c;国际化和消息提示的功能 CopyText组件 1. 功能分…

C++11完美转发(引用折叠、万能引用)

完美转发是指在函数模板中&#xff0c;完全依照模板的参数的类型&#xff0c;将参数传递给函数模板中调用的另外一个函数。 函数模板在向其他函数传递自身形参时&#xff0c;如果相应实参是左值&#xff0c;它就应该被转发为左值&#xff1b;如果相 应实参是右值&#xff0c;它…

创建vite工程,使用框架为Vanilla时,语言是typescript,修改http端口的方法

直接在项目根目录创建 vite.config.ts文件。 在该文件中添加内容&#xff1a; import { defineConfig } from vite;export default defineConfig({server: {port: 7777,}, });最后尝试运行package.json中的Debug

Codeforces Round 953 (Div. 2) A - C 题解

因为有事只做了A-C&#xff0c;都比较简单&#xff0c;全是很简单的思维&#xff0c;明天有空还会添加上D&#xff0c;如果有人需要可以明天常来看看&#xff01; 进入正题&#xff1a; A. Alice and Books 题意&#xff1a;给你n个数字&#xff0c;将这些数字分到两堆里&am…

PD19 Parallels Desktop 虚拟机 安装Windows10系统 操作步骤(保姆级教程,轻松上手)

Mac分享吧 文章目录 效果一、准备工作二、开始安装1、打开pd 19 虚拟机&#xff0c;点击右上角文件&#xff0c;新建2、通过下载好的镜像安装Windows10系统。找到镜像文件位置&#xff0c;安装&#xff0c;配置2、显示安装完成&#xff0c;打开Windows10系统 三、运行测试1、打…

60.WEB渗透测试-信息收集- 端口、目录扫描、源码泄露(8)

免责声明&#xff1a;内容仅供学习参考&#xff0c;请合法利用知识&#xff0c;禁止进行违法犯罪活动&#xff01; 内容参考于&#xff1a; 易锦网校会员专享课 上一个内容&#xff1a;59.WEB渗透测试-信息收集- 端口、目录扫描、源码泄露&#xff08;7&#xff09; 御剑是用…

中小企业使用CRM系统的优势有哪些

中小企业如何在竞争激烈的市场中脱颖而出&#xff1f;除了优秀的产品和服务&#xff0c;一个高效的管理工具也是必不可少的。而客户关系管理&#xff08;CRM&#xff09;系统正是这样一个能帮助企业提升客户体验、优化内部管理流程的重要工具。接下来&#xff0c;让我们一起探讨…