在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("這樣是不會顯示的").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("這樣是不會顯示的").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ū)
















 
 
 

















 
 
 
 