在ArkUI的ETS中实现【插槽】的功能 原创 精华
panda_coder
发布于 2021-11-23 22:54
浏览
10收藏
【本文正在参与优质创作者激励】
距离ETS的发布也有一段时间,也有不少小伙伴通过ETS制作出很多精美的页面,但在我查阅ETS的组件和API中发现,现有版本的ETS并没有插槽的功能。经过一段时间的探索终于找到曲线救国方式实现插槽功能,得以让组件之间进行解耦。
什么是插槽
了解插槽的小伙伴可以跳过
vue官方定义是:插槽是一套内容分发的API,当组件渲染的时候,<slot></slot> 将会被替换为“Your Profile”。插槽内可以包含任何模板代码。
通俗一点就是插槽就像一个占位符,将组件外的内容通过API分发至组件内。
实现步骤
定义一个slot类
旨在提供一个具名的插槽,故定义一个slot类做后续委托。这不是实现的关键点,也可不定义。
class Slot{
name:string="default"
builder:any
constructor (name:string,builder:any){
this.name=name;
this.builder=builder
}
}
创建一个组件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)
}
}
}
}
}
}
构建页面的组件
构建一个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%')
}
}
显示效果
通过图片可以看到,builder1,builder2真实位置是在了CompA的slot处。
重点
上面就提到Slot类可以不用创建,因为实现原理是通过ForEach+Builder
实现,也可以将Builder
通过函数绑定到组件内。
再看一下官方文档中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:"这是第二个插槽"},{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
}
}
©著作权归作者所有,如需转载,请注明出处,否则将追究法律责任
已于2021-11-24 16:01:06修改
赞
11
收藏 10
回复
相关推荐
最近ArkUI确实很热门,感谢楼主分享。
感觉不错
打字时字母K和字母M会互串
我暂时没发现这个问题,有录屏可以在花粉俱乐部反馈
其实就是数据请求后,页面构建的一个方式
非常感谢,这个思路解决了我开发中的实际问题