头图

【高心星出品】

@BuildParam自定义插槽

当开发者需要自定义组件或是封装组件的时候,经常要根据需求定制布局界面效果,这个时候就需要根据不同条件构建不同的布局效果,@BuildParam配合@Build就可以实现将布局界面作为参数来进行传递。

在这里插入图片描述

插槽的声明和调用

需要在子组件中声明一个插槽并且在build函数中调用该插槽,插槽类型为()=>void类型,还需要给该插槽一个空的@builder构建函数。

@BuilderParam slot:()=>void=this.test  //声明一个插槽 插槽函数为()=>void类型
@Builder   test(){} //给插槽一个默认值 否则无法执行
build() {
Column(){
  Text(this.ison?'开':'关') //子组件布局元素
  this.slot()//插槽 需要父组件传递
}.width('100%')
  
}

完整的子组件代码:

@Component
export struct child{
  @Link ison:boolean
  @BuilderParam slot:()=>void=this.test
  @Builder   test(){}
  build() {
  Column(){
    Text(this.ison?'开':'关')
    this.slot()
  }.width('100%')
    
  }
}

插槽的初始化

需要在父组件中定义@builder构建函数,并将该构建函数初始化给子组件的插槽。

父组件定义的构建函数:

@Builder child() //插槽布局
{
  Row(){
  }.width('100%')
  .height('40%')
  .margin({top:20})
  .backgroundColor(this.ison?Color.Red:Color.Black)
}
@Builder child1()//插槽布局
{
  Row(){
  }.width('100%')
  .height('40%')
  .margin({top:20})
  .backgroundColor(Color.Blue)
  .borderRadius(this.ison?'50%':0)
}

父组件调用子组件:

child({ison:this.ison,slot:this.child1})//子组件调用并初始化插槽
  .margin({top:20}).border({width:2})

完整父组件代码:

import { child } from '../component/chacao';

@Entry
@Component
struct Parent {
  @State ison:boolean=false
  @Builder child() //插槽布局
  {
    Row(){
    }.width('100%')
    .height('40%')
    .margin({top:20})
    .backgroundColor(this.ison?Color.Red:Color.Black)
  }
  @Builder child1()//插槽布局
  {
    Row(){
    }.width('100%')
    .height('40%')
    .margin({top:20})
    .backgroundColor(Color.Blue)
    .borderRadius(this.ison?'50%':0)
  }
  build() {
   Column(){
     Toggle({type:ToggleType.Switch,isOn:this.ison}) //父组件元素
       .onChange((isck)=>{
         this.ison=isck
       })
    child({ison:this.ison,slot:this.child1})//子组件调用
      .margin({top:20}).border({width:2})
   }
    .height('100%')
    .width('100%')
    .backgroundColor(Color.Yellow)
    .justifyContent(FlexAlign.Center)
  }
}

this指向问题

由于插槽是在子组件中定义,子组件中调用,而插槽是在父组件中初始化的,所以就牵涉到this指向问题。原则上在哪里调用this指向哪里,所以父组件构建函数中的this执行并非是父组件而是子组件,也就是案例中构建函数中this指的是子组件,这里的“this.ison”指定的是子组件的全局变量ison而不是父组件的。但是编译问题也要在父组件中定义ison并且要求两者进行双向绑定(所以可以看到ison是@link装饰的)。

@Builder child() //插槽布局
{
  Row(){
  }.width('100%')
  .height('40%')
  .margin({top:20})
  .backgroundColor(this.ison?Color.Red:Color.Black) //child中的ison变量
}
@Builder child1()//插槽布局
{
  Row(){
  }.width('100%')
  .height('40%')
  .margin({top:20})
  .backgroundColor(Color.Blue)
  .borderRadius(this.ison?'50%':0) //child中的ison变量
}

如何才能使用父组件的this呢?

需要在调用子组件的时候加上闭包函数。

build() {
   Column(){
     Toggle({type:ToggleType.Switch,isOn:this.ison}) //父组件元素
       .onChange((isck)=>{
         this.ison=isck
       })
    child({ison:this.ison,slot:()=>{this.child1()}})//子组件调用 这个时候this就是当前的父组件了
      .margin({top:20}).border({width:2})
   }
    .height('100%')
    .width('100%')
    .backgroundColor(Color.Yellow)
    .justifyContent(FlexAlign.Center)
  }
}

高心星
1 声望1 粉丝

华为开发者专家(HDE)。 10年教学经验,兼任多家科技公司技术顾问。先后从事JavaEE项目开发、Python爬虫、HarmonyOS移动应用开发等课程的教学工作。参与开发《鸿蒙应用开发基础》和《鸿蒙项目实战》等课程。