OpenHarmony裝飾指定自定義元件:@BuilderParam裝飾器

OpenHarmony開發者社群發表於2023-09-27

當開發者建立了自定義元件,並想對該元件新增特定功能時,例如在自定義元件中新增一個點選跳轉操作。若直接在元件內嵌入事件方法,將會導致所有引入該自定義元件的地方均增加了該功能。為解決此問題,ArkUI引入了@BuilderParam裝飾器,@BuilderParam用來裝飾指向@Builder方法的變數,開發者可在初始化自定義元件時對此屬性進行賦值,為自定義元件增加特定的功能。該裝飾器用於宣告任意UI描述的一個元素,類似slot佔位符。

說明:

從API version 9開始,該裝飾器支援在ArkTS卡片中使用。

裝飾器使用說明

初始化@BuilderParam裝飾的方法

@BuildParam裝飾的方法只能被自定義構建函式(@Builder裝飾的方法)初始化。

●  使用所屬自定義元件的自定義構建函式或者全域性的自定義構建函式,在本地初始化@BuilderParam。

@Builder function GlobalBuilder0() {}
@Component
struct Child {
  @Builder doNothingBuilder() {};
  @BuilderParam aBuilder0: () => void = this.doNothingBuilder;
  @BuilderParam aBuilder1: () => void = GlobalBuilder0;
  build(){}
}

●  用父元件自定義構建函式初始化子元件@BuildParam裝飾的方法。

@Component
struct Child {
  @Builder componentBuilder() {
    Text(`Parent builder `)
  }
  @BuilderParam aBuilder0: () => void = this.componentBuilder;
  build() {
    Column() {
      this.aBuilder0()
    }
  }
}
@Entry
@Component
struct Parent {
  @Builder componentBuilder() {
    Text(`Parent builder `)
  }
  build() {
    Column() {
      Child({ aBuilder0: this.componentBuilder })
    }
  }
}

●  需注意this指向正確。

以下示例中,Parent元件在呼叫this.componentBuilder()時,this.label指向其所屬元件,即“Parent”。@Builder componentBuilder()傳給子元件@BuilderParam aBuilder0,在Child元件中呼叫this.aBuilder0()時,this.label指向在Child的label,即“Child”。對於@BuilderParam aBuilder1,在將this.componentBuilder傳給aBuilder1時,呼叫bind繫結了this,因此其this.label指向Parent的label。

說明:

開發者謹慎使用bind改變函式呼叫的上下文,可能會使this指向混亂。

@Component
struct Child {
  @Builder componentBuilder() {
    Text(`Child builder `)
  }
  label: string = `Child`
  @BuilderParam aBuilder0: () => void = this.componentBuilder;
  @BuilderParam aBuilder1: () => void = this.componentBuilder;
  build() {
    Column() {
      this.aBuilder0()
      this.aBuilder1()
    }
  }
}
@Entry
@Component
struct Parent {
  label: string = `Parent`
  @Builder componentBuilder() {
    Text(`${this.label}`)
  }
  build() {
    Column() {
      this.componentBuilder()
      Child({ aBuilder0: this.componentBuilder, aBuilder1: this.componentBuilder })
    }
  }
}

使用場景

引數初始化元件

@BuilderParam裝飾的方法可以是有引數和無引數的兩種形式,需與指向的@Builder方法型別匹配。@BuilderParam裝飾的方法型別需要和@Builder方法型別一致。

class GlobalBuilderParam {
  label: string = ""
}
@Builder function GlobalBuilder1($$ : GlobalBuilderParam) {
  Text($$.label)
    .width(400)
    .height(50)
    .backgroundColor(Color.Blue)
}
@Component
struct Child {
  @Builder componentBuilder() {
    Text(`Child builder `)
  }
  label: string = 'Child'
  // 無引數類,指向的componentBuilder也是無引數型別
  @BuilderParam aBuilder0: () => void = this.componentBuilder;
  // 有引數型別,指向的GlobalBuilder1也是有引數型別的方法
  @BuilderParam aBuilder1: ($$ : GlobalBuilderParam) => void = this.componentBuilder;
  build() {
    Column() {
      this.aBuilder0()
      this.aBuilder1({label: 'global Builder label' } )
    }
  }
}
@Entry
@Component
struct Parent {
  label: string = 'Parent'
  @Builder componentBuilder() {
    Text(`${this.label}`)
  }
  build() {
    Column() {
      this.componentBuilder()
      Child({ aBuilder0: this.componentBuilder, aBuilder1: GlobalBuilder1 })
    }
  }
}

尾隨閉包初始化元件

在自定義元件中使用@BuilderParam裝飾的屬性時也可透過尾隨閉包進行初始化。在初始化自定義元件時,元件後緊跟一個大括號“{}”形成尾隨閉包場景。

說明:

此場景下自定義元件內有且僅有一個使用@BuilderParam裝飾的屬性。

開發者可以將尾隨閉包內的內容看做@Builder裝飾的函式傳給@BuilderParam。示例如下:

// xxx.ets
class CustomContainerParam {
  header: string = '';
}
@Component
struct CustomContainer {
  @Builder componentCloser() {
    Text(`Custom closer `)
  }
  @Prop header: string = '';
  @BuilderParam closer: () => void = this.componentCloser;
  build() {
    Column() {
      Text(this.header)
        .fontSize(30)
      this.closer()
    }
  }
}
@Builder function specificParam(label1: string, label2: string) {
  Column() {
    Text(label1)
      .fontSize(30)
    Text(label2)
      .fontSize(30)
  }
}
@Entry
@Component
struct CustomContainerUser {
  @State text: string = 'header';
  param: CustomContainerParam = {
    header: this.text
  };
  build() {
    Column() {
      // 建立CustomContainer,在建立CustomContainer時,透過其後緊跟一個大括號“{}”形成尾隨閉包
      // 作為傳遞給子元件CustomContainer @BuilderParam closer: () => void的引數
      CustomContainer(this.param) {
        Column() {
          specificParam('testA', 'testB')
        }.backgroundColor(Color.Yellow)
        .onClick(() => {
          this.text = 'changeHeader';
        })
      }
    }
  }
}


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/70011554/viewspace-2986377/,如需轉載,請註明出處,否則將追究法律責任。

相關文章