在ArkUI的ETS中實(shí)現(xiàn)【插槽】的功能
51CTO和華為官方合作共建的鴻蒙技術(shù)社區(qū)
距離ETS的發(fā)布也有一段時(shí)間,也有不少小伙伴通過ETS制作出很多精美的頁面,但在我查閱ETS的組件和API中發(fā)現(xiàn),現(xiàn)有版本的ETS并沒有插槽的功能。經(jīng)過一段時(shí)間的探索終于找到曲線救國方式實(shí)現(xiàn)插槽功能,得以讓組件之間進(jìn)行解耦。
什么是插槽
了解插槽的小伙伴可以跳過
vue官方定義是:插槽是一套內(nèi)容分發(fā)的API,當(dāng)組件渲染的時(shí)候,
通俗一點(diǎn)就是插槽就像一個(gè)占位符,將組件外的內(nèi)容通過API分發(fā)至組件內(nèi)。
實(shí)現(xiàn)步驟
定義一個(gè)slot類
旨在提供一個(gè)具名的插槽,故定義一個(gè)slot類做后續(xù)委托。這不是實(shí)現(xiàn)的關(guān)鍵點(diǎn),也可不定義。
- class Slot{
- name:string="default"
- builder:any
- constructor (name:string,builder:any){
- this.name=name;
- this.builder=builder
- }
- }
創(chuàng)建一個(gè)組件CompA
創(chuàng)建一個(gè)自定義組件CompA,并提供兩個(gè)具名插槽的處理,一個(gè)defualt,一個(gè)slot2。
- @Component
- struct CompA{
- @State text:string=""
- @State data:string[]=[]
- @State slot:Slot=new Slot(null)
- build(){
- Column(){
- Column(){
- Text("CompA組件內(nèi)的內(nèi)容")
- .fontColor("#00F")
- .fontSize(16)
- .margin(10)
- }
- Column(){
- Row(){
- if(this.slot.name=="default"){
- ForEach(["這是默認(rèn)插槽【default】"],
- this.slot.builder)
- }
- if(this.slot.name=="slot2"){
- ForEach(this.data,
- this.slot.builder)
- }
- }
- }
- }
- }
- }
構(gòu)建頁面的組件
構(gòu)建一個(gè)Index的頁面,在頁面內(nèi)創(chuàng)建兩個(gè)Buider bulder1 ,builder2,并實(shí)例化兩個(gè)Slot類slot1、slot2,將builder1,builder2分別給到slot1,slot2。
builder1內(nèi)通過Text組件顯示一段文字。
builder2內(nèi)通構(gòu)建稍微復(fù)雜一點(diǎn)的模型,設(shè)置一個(gè)文字和二維碼。
- @Entry
- @Component
- struct Index {
- @Builder builder1(str:string){
- Text(str).fontSize(18).fontColor("#f00")
- }
- @Builder builder2(obj:any){
- Column(){
- Row(){
- Text(obj.title).fontSize(16)
- }
- Row(){
- QRCode(obj.title).width(100).height(100)
- }.margin(10)
- }.margin(10)
- }
- slot1:Slot=new Slot(this.builder1)
- slot2:Slot=new Slot(this.builder2,"slot2")
- build() {
- Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
- Column(){
- CompA(){
- Text("這樣是不會(huì)顯示的").fontSize(24)
- }
- CompA({slot:this.slot1})
- CompA({slot:this.slot2,data:[{title:"這是第二個(gè)插槽"},{title:"http://www.baidu.com"}]})
- }
- }
- .width('100%')
- .height('100%')
- }
- }
顯示效果:

通過圖片可以看到,builder1,builder2真實(shí)位置是在了CompA的slot處。
重點(diǎn)
上面就提到Slot類可以不用創(chuàng)建,因?yàn)閷?shí)現(xiàn)原理是通過ForEach+Builder實(shí)現(xiàn),也可以將Builder通過函數(shù)綁定到組件內(nèi)。
再看一下官方文檔中ForEach:

全部代碼供參考
- @Entry
- @Component
- struct Index {
- @Builder builder1(str:string){
- Text(str).fontSize(18).fontColor("#f00")
- }
- @Builder builder2(obj:any){
- Column(){
- Row(){
- Text(obj.title).fontSize(16)
- }
- Row(){
- QRCode(obj.title).width(100).height(100)
- }.margin(10)
- }.margin(10)
- }
- slot1:Slot=new Slot(this.builder1)
- slot2:Slot=new Slot(this.builder2,"slot2")
- build() {
- Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
- Column(){
- CompA(){
- Text("這樣是不會(huì)顯示的").fontSize(24)
- }
- CompA({slot:this.slot1})
- CompA({slot:this.slot2,data:[{title:"這是第二個(gè)插槽"},{title:"http://www.baidu.com"}]})
- }
- }
- .width('100%')
- .height('100%')
- }
- }
- @Component
- struct CompA{
- @State text:string=""
- @State data:string[]=[]
- @State slot:Slot=new Slot(null)
- build(){
- Column(){
- Column(){
- Text("CompA組件內(nèi)的內(nèi)容")
- .fontColor("#00F")
- .fontSize(16)
- .margin(10)
- }
- Column(){
- Row(){
- if(this.slot.name=="default"){
- ForEach(["這是默認(rèn)插槽【default】"],
- this.slot.builder)
- }
- if(this.slot.name=="slot2"){
- ForEach(this.data,
- this.slot.builder)
- }
- }
- }
- }
- }
- }
- class Slot{
- name:string="default"
- builder:any
- constructor (builder:any,name?:string){
- name && (this.name=name);
- this.builder=builder
- }
- }
51CTO和華為官方合作共建的鴻蒙技術(shù)社區(qū)