鸿蒙开发 - 自定义组件 和 组件通信的方法

自定义组件的基本结构

typescript 复制代码
@Entry
@Component
struct MyComponent {
  build(){
     // ...
  }
}
  • build()函数

build()函数用于描述组件的UI界面,自定义组件必须定义build()函数

typescript 复制代码
build() {
  Column() {
    Text('测试')
    Button('点击')
  }
}
  • struct 关键字

strcut 用来声明数据结构 struct + 自定组件名 + { ... }

struct@Component 装饰后,必须要要有 build() 函数

typescript 复制代码
struct MyComponent {
}
  • @Component 装饰器

@Component 用来声明一个组件

  1. @Componentstruct 两者配对使用
  2. @Component只能装饰 struct 关键字声明的数据结构
typescript 复制代码
@Component 
struct MyComponent {
  build() {
  }
}
  • @Entry 装饰器

使用 @Entry 用于标记一个页面的入口点。当用户打开应用或导航路由的时候,展示的就是这个组件

typescript 复制代码
@Entry
@Component
struct MyComponent {
  build() {
  }
}

组件通信

父子间单向传递 @Prop

@Prop 单向传递数据:父组件数据变化,会通知子组件,但子组件数据变化,不会通知父组件

  1. 子组件深拷贝父组件传过来的数据,父组件发生数据变更,子组件会跟着变化
  2. 子组件也可以自己更新数据,但不会同步父组件数据

举例:父组件向子组件传递一个数据 text,默认值是 123,当点击按钮的时候,更新 text 的值为 456

  • 父组件
typescript 复制代码
import Child from './Child'

@Entry
@Component
struct Parent {
  @State text: string = '123'

  build() {
    Column() {
      Button(`按钮:${this.text}`)
        .onClick(() => {
          this.text = '456'
        })

      Child({ text: this.text })
    }
  }
}
  • 子组件

子组件使用 @Prop 装饰器进行修饰变量

typescript 复制代码
@Component
export default struct Child {
  @Prop text: string = ''

  build() {
    Row() {
      Text(`父组件传过来的内容:${this.text}`)
    }
  }
}

按钮点击前:

按钮点击后:

需要注意的是: 当父组件发生数据变更,子组件如果想跟着改变,就需要使用 @Prop 声明变量 @Prop text:string = ''。当然如果不需要跟着改变,也可以直接这么写 text:string = '',相当于将text的初始值传过去了,后续不会跟着变化

@Link 双向传递数据:父组件发生数据变化,会通知子组件,同时子组件数据变化,也通知父组件

使用 @Link,替换掉 @Prop,即 @Link text:string

需要注意的是: 使用 @Link 修饰的变量,不需要进行初始化,也就是不需要附一个初始值

typescript 复制代码
// 子组件

@Component
export default struct Child {
  @Link text: string

  build() {
    Column() {
      Text(`父组件传过来的内容:${this.text}`)

      Button('更改父组件传过来的数据')
        .onClick(() => {
          this.text = '789'
        })
    }
  }
}

当子组件点了更改数据的按钮,父组件也跟着发生了变化,效果图如下,

子组件调用父组件的方法

和传数据类似,只不过现在传递一个函数方法

  • 父组件

父组件定义一个方法 click, 传给子组件

typescript 复制代码
import Child from './Child'

@Entry
@Component
struct Parent {
  @State count: number = 0
  click: () => void = () => {
    this.count++
  }

  build() {
    Column() {
      Text(`点击次数:${this.count}`)

      Child({ parentClick: this.click })
    }
  }
}
  • 子组件

子组件声明父组件传过来的 parentClick 函数,调用即可

typescript 复制代码
@Component
export default struct Child {
  parentClick?: () => void

  build() {
    Column() {
      Button('点击')
        .onClick(() => {
          if (this.parentClick) {
            this.parentClick()
          }
        })
    }
  }
}

初始化效果图:

子组件调用父组件方法后:

跨组件双向通信(@Provide 和 @Consume)

使用@Provide@Consume 实现跨组件通信,这种方式是双向的,不管祖先组件还是后代组件发生数据变更,另外一方都会实时变化

祖先组件使用 @Provide 注入数据

typescript 复制代码
@Provide text: string = '123'

后代组件使用 @Consume 接收

typescript 复制代码
@Consume text: string

注意: @Consume 同样不需要初始化

eventHub 事件总线

eventHub 提供了事件中心,提供了监听事件和触发事件的能力,从而实现跨组件通信。(很接近vue的eventBus)

  • 祖先组件
typescript 复制代码
@Entry
@Component
struct Parent{
  build() {
    Column() {
      Button('发送')
        .onClick(() => {
          getContext(this).eventHub.emit('init', 2)
        })
    }
  }
}
  • 后代组件

后代组件中,先建立起监听事件,

typescript 复制代码
@Component
export default struct Grandchild {
  @State value: number = 1

  aboutToAppear(): void {
    getContext(this).eventHub.on('init', (data: number) => {
      this.handleMessage(data)
    })
  }

  handleMessage(value: number) {
    this.value = value
  }

  build() {
    Text(`接收到父组件发送的数据:${this.value}`)
  }
}
方法
  • on(event: string, callback: Function) 监听事件
  • emit(event: string, ...args: Object[]) 触发事件
  • off(event: string, callback?: Function) 取消订阅的指定事件
    • 传入 callback:取消指定的 callback 对指定事件的订阅,当该事件触发后,将不会再回调该callback。
    • 不传 callback:取消所有 callback 对指定事件的订阅。
相关推荐
敢嗣先锋几秒前
鸿蒙5.0实战案例:基于ImageKit对图片进行处理
移动开发·harmonyos·arkui·组件化·鸿蒙开发
陈无左耳、几秒前
HarmonyOS学习第3天: 环境搭建开启鸿蒙开发新世界
学习·华为·harmonyos
敢嗣先锋5 分钟前
鸿蒙5.0实战案例:基于ArkUI的验证码实现
移动开发·harmonyos·openharmony·arkui·鸿蒙开发
别说我什么都不会3 小时前
鸿蒙轻内核M核源码分析系列十二 事件Event
操作系统·harmonyos
Huang兄4 小时前
鸿蒙-canvas-刮刮乐
华为·harmonyos
Sharknade4 小时前
鸿蒙-阻塞式文件锁
华为·harmonyos
敢嗣先锋4 小时前
鸿蒙5.0实战案例:基于原生能力的深色模式适配
ui·移动开发·harmonyos·arkui·组件化·鸿蒙开发
Huang兄5 小时前
鸿蒙-验证码输入框的几种实现方式-上
harmonyos
二川bro5 小时前
前端如何转战鸿蒙
华为·harmonyos
陈无左耳、11 小时前
HarmonyOS学习第2天: 解锁语言与框架的无限可能
学习·华为·harmonyos