在ArkUI的ETS中实现【插槽】的功能

插槽是一套内容分发的API,当组件渲染的时候,将会被替换为“Your Profile”。插槽内可以包含任何模板代码。
首页 新闻资讯 行业资讯 在ArkUI的ETS中实现【插槽】的功能

[[436541]]

想了解更多内容,请访问:

51CTO和华为官方合作共建的鸿蒙技术社区

https://harmonyos.51cto.com

距离ETS的发布也有一段时间,也有不少小伙伴通过ETS制作出很多精美的页面,但在我查阅ETS的组件和API中发现,现有版本的ETS并没有插槽的功能。经过一段时间的探索终于找到曲线救国方式实现插槽功能,得以让组件之间进行解耦。

什么是插槽

了解插槽的小伙伴可以跳过

vue官方定义是:插槽是一套内容分发的API,当组件渲染的时候, 将会被替换为“Your  Profile”。插槽内可以包含任何模板代码。

通俗一点就是插槽就像一个占位符,将组件外的内容通过API分发至组件内。

实现步骤

定义一个slot类

旨在提供一个具名的插槽,故定义一个slot类做后续委托。这不是实现的关键点,也可不定义。

复制

class Slot{   name:string="default"   builder:any    constructor (name:string,builder:any){     this.name=name;     this.builder=builder   } }
  • 1.

  • 2.

  • 3.

  • 4.

  • 5.

  • 6.

  • 7.

  • 8.

  • 9.

创建一个组件CompA

创建一个自定义组件CompA,并提供两个具名插槽的处理,一个defualt,一个slot2。

复制

@Component struct CompA{   @State text:string=""   @State data:string[]=[]   @State slot:Slot=new Slot(null)   build(){     Column(){       Column(){         Text("CompA组件内的内容")         .fontColor("#00F")         .fontSize(16)         .margin(10)       }       Column(){         Row(){           if(this.slot.name=="default"){             ForEach(["这是默认插槽【default】"],               this.slot.builder)           }           if(this.slot.name=="slot2"){             ForEach(this.data,               this.slot.builder)           }         }       }     }   } }
  • 1.

  • 2.

  • 3.

  • 4.

  • 5.

  • 6.

  • 7.

  • 8.

  • 9.

  • 10.

  • 11.

  • 12.

  • 13.

  • 14.

  • 15.

  • 16.

  • 17.

  • 18.

  • 19.

  • 20.

  • 21.

  • 22.

  • 23.

  • 24.

  • 25.

  • 26.

  • 27.

  • 28.

构建页面的组件

构建一个Index的页面,在页面内创建两个Buider bulder1  ,builder2,并实例化两个Slot类slot1、slot2,将builder1,builder2分别给到slot1,slot2。

builder1内通过Text组件显示一段文字。

builder2内通构建稍微复杂一点的模型,设置一个文字和二维码。

复制

@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("这样是不会显示的").fontSize(24)          }         CompA({slot:this.slot1})         CompA({slot:this.slot2,data:[{title:"这是第二个插槽"},{title:"http://www.baidu.com"}]})       }     }     .width('100%')     .height('100%')   } }
  • 1.

  • 2.

  • 3.

  • 4.

  • 5.

  • 6.

  • 7.

  • 8.

  • 9.

  • 10.

  • 11.

  • 12.

  • 13.

  • 14.

  • 15.

  • 16.

  • 17.

  • 18.

  • 19.

  • 20.

  • 21.

  • 22.

  • 23.

  • 24.

  • 25.

  • 26.

  • 27.

  • 28.

  • 29.

  • 30.

  • 31.

  • 32.

  • 33.

  • 34.

  • 35.

显示效果:

在ArkUI的ETS中实现【插槽】的功能-鸿蒙HarmonyOS技术社区

通过图片可以看到,builder1,builder2真实位置是在了CompA的slot处。

重点

上面就提到Slot类可以不用创建,因为实现原理是通过ForEach+Builder实现,也可以将Builder通过函数绑定到组件内。

再看一下官方文档中ForEach:

在ArkUI的ETS中实现【插槽】的功能-鸿蒙HarmonyOS技术社区

全部代码供参考

复制

@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("这样是不会显示的").fontSize(24)          }         CompA({slot:this.slot1})         CompA({slot:this.slot2,data:[{title:"这是第二个插槽"},{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组件内的内容")         .fontColor("#00F")         .fontSize(16)         .margin(10)       }       Column(){         Row(){           if(this.slot.name=="default"){             ForEach(["这是默认插槽【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   } }
  • 1.

  • 2.

  • 3.

  • 4.

  • 5.

  • 6.

  • 7.

  • 8.

  • 9.

  • 10.

  • 11.

  • 12.

  • 13.

  • 14.

  • 15.

  • 16.

  • 17.

  • 18.

  • 19.

  • 20.

  • 21.

  • 22.

  • 23.

  • 24.

  • 25.

  • 26.

  • 27.

  • 28.

  • 29.

  • 30.

  • 31.

  • 32.

  • 33.

  • 34.

  • 35.

  • 36.

  • 37.

  • 38.

  • 39.

  • 40.

  • 41.

  • 42.

  • 43.

  • 44.

  • 45.

  • 46.

  • 47.

  • 48.

  • 49.

  • 50.

  • 51.

  • 52.

  • 53.

  • 54.

  • 55.

  • 56.

  • 57.

  • 58.

  • 59.

  • 60.

  • 61.

  • 62.

  • 63.

  • 64.

  • 65.

  • 66.

  • 67.

  • 68.

  • 69.

想了解更多内容,请访问:

51CTO和华为官方合作共建的鸿蒙技术社区

https://harmonyos.51cto.com

 

45    2021-11-26 10:08:57    鸿蒙 HarmonyOS 应用