鸿蒙Harmony Os中的@Builder / @BuilderParam

鸿蒙Harmony Os中的@Builder / @BuilderParam

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

  1. 作用: 可以将重复使用的UI元素抽象成一个方法,并在 build 方法中进行调用。

  2. 使用范围: 组件内部或全局范围进行定义和使用。

    • 组件内定义

      less 复制代码
      @Builder MyBuilderFun() {}
      
      使用: this.MyBuilderFun()
    • 全局范围定义

      less 复制代码
      @Builder function MyBuilderFun() {}
      
      使用: MyGlobalBuilderFun()
  3. demo,使用@Builder提取结构

    • 全局声明需要加function关键字,使用时直接写函数名称。
    scss 复制代码
    @Entry
    @Component
    struct Demo {
      build() {
          Column({space:10}) {
            ListModel()
          }.width('100%')
          .height('100%')
      }
    }
    
    @Builder
    function ListModel(){
       Row(){
         Text("音乐")
           .width("100%")
           .height(40)
           .textAlign(TextAlign.Center)
           .fontColor(Color.White)
       }
       .width("100%")
       .height(100)
       .backgroundColor(Color.Brown)
    }
    • 组件内声明,使用时需要用this
    scss 复制代码
    @Entry
    @Component
    struct Demo {
    
    @Builder
    ListModel(){
       Row(){
         Text("音乐")
           .width("100%")
           .height(40)
           .textAlign(TextAlign.Center)
           .fontColor(Color.White)
       }
       .width("100%")
       .height(100)
       .backgroundColor(Color.Brown)
    }
      build() {
          Column({space:10}) {
            this.ListModel()
          }.width('100%')
          .height('100%')
      }
    }
  4. 支持传递参数,动态渲染ui

    ![图片转存失败,建议将图片保存下来直接上传](/Users/chengang/Library/Application Support/typora-user-images/image-20240304113431754.png)

    1. 值传递

      scss 复制代码
      @Entry
      @Component
      struct Demo {
      
      @Builder
      ListModel({ title: string }){
         Row(){
           Text(title)
             .width("100%")
             .height(40)
             .textAlign(TextAlign.Center)
             .fontColor(Color.White)
         }
         .width("100%")
         .height(100)
         .backgroundColor(Color.Brown)
      }
        build() {
            Column({space:10}) {
               	this.ListModel("音乐")
                this.ListModel("美术")
                this.ListModel("舞蹈")
            }.width('100%')
            .height('100%')
        }
      }
    2. 引用数据类型的传递

      ![图片转存失败,建议将图片保存下来直接上传](/Users/chengang/Library/Application Support/typora-user-images/image-20240304113903374.png)

      scss 复制代码
      @Builder
      function ListModel(params:{title:string,count:number}){
         Row(){
           Text(`${params.title}`)
             .height(40)
             .textAlign(TextAlign.Center)
             .fontColor(Color.White)
      
           Text(`投票人数:${params.count}`)
             .fontColor(Color.White)
         }
         .width("100%")
         .height(100)
         .backgroundColor(Color.Brown)
          .justifyContent(FlexAlign.SpaceAround)
      }
      
      @Entry
      @Component
      struct Index {
        @State CountMusic:number=10
        build() {
            Column({space:10}) {
              ListModel({title:"音乐",count:this.CountMusic})
              ListModel({title:"美术",count:30})
              ListModel({title:"舞蹈",count:12})
      
              Button("增加音乐支持人数").onClick(()=>{
                this.CountMusic++;
              })
            }.width('100%')
            .height('100%')
        }
      }
  5. 总结:

    • 在使用 @Builder 复用逻辑时,可以支持传递参数,从而实现更灵活的UI渲染。
    • 参数可以是状态数据,但建议使用对象的方式进行传递(直接传递,无法实现视图更新)。
    • 可以使用 Component 来抽象组件,而 @Builder 则可以实现轻量级的UI复用。

二. @BuilderParam:是一个装饰器,用于声明任意UI描述的一个元素,类似于vue里的 slot 占位符。

  1. 作用: "插槽"类似,注意(@BuilderParam装饰的方法只能被自定义构建函数(@Builder装饰的方法)初始化。)

  2. 使用场景

    • 尾随闭包初始化组件demo(默认插槽)

      标题通过文字属性传入,内容通过"尾随闭包传入"

      scss 复制代码
      // ● 标题文字通过属性传入
      // ● 内容结构"尾随闭包"传入
      @Entry
      @Component
      struct Index {
      
        build() {
          Column({ space: 10 }) {
            ListModel({title:"音乐"}){
              Text("音乐的内容")
            }
            ListModel({title:"美术"}){
              Text("美术的内容")
            }
            ListModel({title:"舞蹈"})
          }.width('100%').height('100%')
        }
      }
      
      @Component
      struct ListModel {
        title: string
        // ListContent 名字随便起,默认接收一个自定义构建函数
        @BuilderParam ListContent: () => void = this.defaultContent; 
      
        @Builder defaultContent () {
          Text('默认展示的内容')
        }
      
        build() {
          Column() {
            Text(this.title)
              .width('100%')
              .height(50)
              .textAlign(TextAlign.Center)
            this.ListContent();
          }.width('100%').height(200).backgroundColor(Color.Brown)
        }
      }
    • 参数初始化组件demo(具名插槽)

      需要传入头部结构和底部结构

      scss 复制代码
      // 需求:需要传入头部结构和底部结构
      @Entry
      @Component
      struct Index {
      
        @Builder ListHeaderContent () {
          Text("头部内容")
            .fontColor(Color.White)
            .height(40)
            .backgroundColor(Color.Blue)
            .width("100%")
            .textAlign(TextAlign.Center)
        }
      
        @Builder ListEndContent () {
          Text("尾部内容")
            .fontColor(Color.White)
            .height(40)
            .backgroundColor(Color.Blue)
            .width("100%")
            .textAlign(TextAlign.Center)
        }
      
        build() {
          Column() {
            ListModel({
              title: '音乐',
              ListHeader: this.ListHeaderContent,
              ListEnd: () => {this.ListEndContent()} // 箭头函数
            })
          }.width('100%').height('100%')
        }
      }
      
      
      @Component
      struct ListModel {
        title: string
        @BuilderParam ListHeader: () => void = this.defaultHeader;
        @BuilderParam ListEnd: () => void = this.defaultEnd;
      
        @Builder defaultHeader() {
          Text('默认 header')
        }
        @Builder defaultEnd() {
          Text('默认 End')
        }
      
        build() {
          Column() {
            this.ListHeader();
            Text(this.title)
              .width("100%")
              .height(40)
              .textAlign(TextAlign.Center)
              .fontColor(Color.White)
      
            this.ListEnd();
          }.width('100%').height(200).backgroundColor(Color.Brown)
        }
      }

      这不就是类似于vue的具名插槽吗???提取一个公共组件,引入,定制头和尾!!!

  3. 总结

    • 当子组件使用一个 @BuilderParam 时,使用组件时可以在尾随的大括号 {} 中插入UI结构。
    • 当子组件使用多个 @BuilderParam 时,可以在使用组件时传入参数,例如 Comp({ xxx: this.builderFn })
    • 不能既传递默认插槽也传递具名插槽,会报错。
    • 子组件本身可以提供一个默认的 @Builder 函数,作为 @BuilderParam 的备用函数,用于作为备用内容。
相关推荐
y先森1 小时前
CSS3中的伸缩盒模型(弹性盒子、弹性布局)之伸缩容器、伸缩项目、主轴方向、主轴换行方式、复合属性flex-flow
前端·css·css3
前端Hardy1 小时前
纯HTML&CSS实现3D旋转地球
前端·javascript·css·3d·html
susu10830189111 小时前
vue3中父div设置display flex,2个子div重叠
前端·javascript·vue.js
IT女孩儿2 小时前
CSS查缺补漏(补充上一条)
前端·css
吃杠碰小鸡3 小时前
commitlint校验git提交信息
前端
虾球xz4 小时前
游戏引擎学习第20天
前端·学习·游戏引擎
我爱李星璇4 小时前
HTML常用表格与标签
前端·html
疯狂的沙粒4 小时前
如何在Vue项目中应用TypeScript?应该注意那些点?
前端·vue.js·typescript
小镇程序员4 小时前
vue2 src_Todolist全局总线事件版本
前端·javascript·vue.js
野槐4 小时前
前端图像处理(一)
前端