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

时间:2022-02-08 16:24:43

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

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

什么是插槽

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

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

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

实现步骤

定义一个slot类

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

  1. class Slot{
  2. name:string="default"
  3. builder:any
  4.  
  5. constructor (name:string,builder:any){
  6. this.name=name;
  7. this.builder=builder
  8. }
  9. }

创建一个组件CompA

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

  1. @Component
  2. struct CompA{
  3. @State text:string=""
  4. @State data:string[]=[]
  5. @State slot:Slot=new Slot(null)
  6. build(){
  7. Column(){
  8. Column(){
  9. Text("CompA组件内的内容")
  10. .fontColor("#00F")
  11. .fontSize(16)
  12. .margin(10)
  13. }
  14. Column(){
  15. Row(){
  16. if(this.slot.name=="default"){
  17. ForEach(["这是默认插槽【default】"],
  18. this.slot.builder)
  19. }
  20. if(this.slot.name=="slot2"){
  21. ForEach(this.data,
  22. this.slot.builder)
  23. }
  24. }
  25. }
  26. }
  27. }
  28. }

构建页面的组件

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

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

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

  1. @Entry
  2. @Component
  3. struct Index {
  4. @Builder builder1(str:string){
  5. Text(str).fontSize(18).fontColor("#f00")
  6. }
  7.  
  8. @Builder builder2(obj:any){
  9. Column(){
  10. Row(){
  11. Text(obj.title).fontSize(16)
  12. }
  13. Row(){
  14. QRCode(obj.title).width(100).height(100)
  15. }.margin(10)
  16. }.margin(10)
  17. }
  18.  
  19. slot1:Slot=new Slot(this.builder1)
  20. slot2:Slot=new Slot(this.builder2,"slot2")
  21.  
  22. build() {
  23. Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
  24. Column(){
  25. CompA(){
  26. Text("这样是不会显示的").fontSize(24)
  27. }
  28. CompA({slot:this.slot1})
  29. CompA({slot:this.slot2,data:[{title:"这是第二个插槽"},{title:"http://www.baidu.com"}]})
  30. }
  31. }
  32. .width('100%')
  33. .height('100%')
  34. }
  35. }

显示效果:

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

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

重点

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

再看一下官方文档中ForEach:

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

全部代码供参考

  1. @Entry
  2. @Component
  3. struct Index {
  4. @Builder builder1(str:string){
  5. Text(str).fontSize(18).fontColor("#f00")
  6. }
  7. @Builder builder2(obj:any){
  8. Column(){
  9. Row(){
  10. Text(obj.title).fontSize(16)
  11. }
  12. Row(){
  13. QRCode(obj.title).width(100).height(100)
  14. }.margin(10)
  15. }.margin(10)
  16. }
  17. slot1:Slot=new Slot(this.builder1)
  18. slot2:Slot=new Slot(this.builder2,"slot2")
  19. build() {
  20. Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
  21. Column(){
  22. CompA(){
  23. Text("这样是不会显示的").fontSize(24)
  24. }
  25. CompA({slot:this.slot1})
  26. CompA({slot:this.slot2,data:[{title:"这是第二个插槽"},{title:"http://www.baidu.com"}]})
  27. }
  28. }
  29. .width('100%')
  30. .height('100%')
  31. }
  32. }
  33.  
  34. @Component
  35. struct CompA{
  36. @State text:string=""
  37. @State data:string[]=[]
  38. @State slot:Slot=new Slot(null)
  39. build(){
  40. Column(){
  41. Column(){
  42. Text("CompA组件内的内容")
  43. .fontColor("#00F")
  44. .fontSize(16)
  45. .margin(10)
  46. }
  47. Column(){
  48. Row(){
  49. if(this.slot.name=="default"){
  50. ForEach(["这是默认插槽【default】"],
  51. this.slot.builder)
  52. }
  53. if(this.slot.name=="slot2"){
  54. ForEach(this.data,
  55. this.slot.builder)
  56. }
  57. }
  58. }
  59. }
  60. }
  61. }
  62. class Slot{
  63. name:string="default"
  64. builder:any
  65. constructor (builder:any,name?:string){
  66. name && (this.name=name);
  67. this.builder=builder
  68. }
  69. }

原文链接:https://harmonyos.51cto.com

相关文章