我在学习鸿蒙开发前学习过许多前端技术,框架什么的,但是发现鸿蒙声明式开发范式中似乎没有插槽的类似东西,就查看了其他人的文章加上所学的知识研究了一下,本文章从头到尾讲述了声明式开发范式中的插槽,包括传入可点击的按钮什么的使用方法,如果还想知道更多的使用方式可以联系我。(第一次写文章,不好轻点喷)

 一、基础知识

  • 这里是给没接触过插槽的朋友们看的,插槽是前端一个常用的思想,用于向自定义组件中传入一个组件,使自定义组件的灵活性更高,代码复用率更高。

二、 鸿蒙声明式开发范式中实现插槽

以下是解释+示例,示例是一个自定义标题栏,也是非常实用。

  • 先解释一下吧,自定义组件可以用@BuilderParam接收从父组件传下来的组件,并且使用(非常基础,有很多参考资料),接下来就是需要从子组件修改父组件的数据,@Link很好用,但是每次使用的时候都需要传一个数据到子组件才能进行修改,对于其他使用地方非常不友好,因为@Link传的数据是必须传入的,也就是说使用@Link的时候需要在同一个组件使用的地方都传入相关数据,非常的多余。但是有一个emitter就能解决该问题,emitter用法参考官方文档:
  • 文档中心https://developer.huawei.com/consumer/cn/doc/harmonyos-references-V13/js-apis-emitter-V13
  • emitter的具体作用就是提供了在同一进程不同线程间,或同一进程同一线程内,发送和处理事件的能力,包括持续订阅事件、单次订阅事件、取消订阅事件,以及发送事件到事件队列的能力。(学过vue框架的会觉得非常眼熟)。接下来是示例+解释(预览请使用模拟器,预览器无法进行预览)。

1、基础样式

// 父组件样式
import { MyHeader } from '../component/MyHeader'

@Entry
@Component
struct TestPage {
  @State message: string = 'Hello World'
  @Builder
  buttons() {
    Button('点击改变数据', {type: ButtonType.Normal})
      .backgroundColor(Color.Transparent)
      .onClick(() => {
        
      })
  }
  build(){
    Column({space: 20}){
      MyHeader({
        Left_Message: '返回上一页',
        right_box: this.buttons
      })
      Text(this.message)
    }
    .width('100%')
    .height('100%')
  }
}
// 子组件样式

@Builder
function rightBox() {
  Text('默认组件')
}
@Component
export struct MyHeader{

  @Prop Left_Message: string
  @Prop isBack: boolean = true
  @BuilderParam right_box: () => void = rightBox
  build() {
    Row(){
      if(this.isBack){
        Image($r('app.media.back'))
          .height('50%')
          .onClick(() => {
            // router.back()
          })
      }
      Text(this.Left_Message)
        .fontSize(20)
      Blank()
      this.right_box()
    }.width('100%')
    .height(70)
    .padding({
      top: 17,
      left: 10,
      right: 10
    })
    .backgroundColor('#DFCEB4')
  }
}
  • 这个只是规定了自定义组件,然后传入一个区域可以用于接收从父组件传下来的组件,可以复制粘贴到编译器中查看效果,后续子组件修改父组件的数据效果将会依次添加。

2.添加emitter

  • 在父组件传入子组件的buttons区域的按钮点击事件onClick中添加如下代码
        let eventData: emitter.EventData = {
          data: {
            content: "message",
            value: 'Hello ArkTS'
          }
        }
        emitter.emit('changeData', eventData)

eventData是在规定发送事件的时候传递的参数,按照格式:键:值的方式传递(官方文档有),emitter.emit传递两个参数,changeData为eventId,eventData就是数据了。

相关使用方法也可以参考作者的另外一篇文章:

https://blog.csdn.net/Liang_beginning/article/details/147282974?spm=1001.2014.3001.5502https://blog.csdn.net/Liang_beginning/article/details/147282974?spm=1001.2014.3001.5502

3.父组件添加持续订阅事件

  • 然后在父组件中添加持续监听事件,如下:
aboutToAppear(): void {
    emitter.on('changeData', (res) => {
      let theData: myContent = res.data as myContent
      this.message = theData.value
    })
  }

这样就可以在父组件中持续监听以changeData这个事件ID传入的了,emitter.on是一直监听,如果想监听一次可以使用emitter.once(详情请参考官方文档)。

大概效果如下:


然后你就能在不传入子组件的情况下,在子组件中修改父组件的参数,个人觉得很好用,初学者,勿喷,有什么问题也欢迎交流,如果你喜欢本文章,给个点赞关注评论吧,谢谢了。

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐