鸿蒙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 的备用函数,用于作为备用内容。
相关推荐
雪落满地香7 分钟前
前端:改变鼠标点击物体的颜色
前端
余生H39 分钟前
前端Python应用指南(二)深入Flask:理解Flask的应用结构与模块化设计
前端·后端·python·flask·全栈
outstanding木槿44 分钟前
JS中for循环里的ajax请求不数据
前端·javascript·react.js·ajax
酥饼~1 小时前
html固定头和第一列简单例子
前端·javascript·html
一只不会编程的猫1 小时前
高德地图自定义折线矢量图形
前端·vue.js·vue
m0_748250931 小时前
html 通用错误页面
前端·html
来吧~1 小时前
vue3使用video-player实现视频播放(可拖动视频窗口、调整大小)
前端·vue.js·音视频
han_1 小时前
不是哥们,我的console.log突然打印不出东西了!
前端·javascript·chrome
魔术师卡颂1 小时前
最近看到太多 cursor 带来的焦虑,有些话想说
前端·aigc·openai
鎈卟誃筅甡1 小时前
Vuex 的使用和原理详解
前端·javascript