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

自定义组件的基本结构

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 对指定事件的订阅。
相关推荐
zhanshuo19 分钟前
干掉复杂逻辑!手把手教你在鸿蒙系统中创建稳定的后台服务
harmonyos
zhanshuo19 分钟前
鸿蒙系统通知开发全攻略:实现跳转、自动消失、消息提醒的完整教程
harmonyos
问道飞鱼1 小时前
【移动端知识】移动端多 WebView 互访方案:Android、iOS 与鸿蒙实现
android·ios·harmonyos·多webview互访
周胡杰2 小时前
鸿蒙加载预置数据库-关系型数据库-如何读取本地/预制数据库
数据库·华为·harmonyos·鸿蒙
迷曳12 小时前
27、鸿蒙Harmony Next开发:ArkTS并发(Promise和async/await和多线程并发TaskPool和Worker的使用)
前端·华为·多线程·harmonyos
迷曳16 小时前
24、鸿蒙Harmony Next开发:不依赖UI组件的全局自定义弹出框 (openCustomDialog)
dialog·前端·ui·harmonyos·鸿蒙
平谷一勺1 天前
鸿蒙状态栏操作
华为·harmonyos·沉浸式状态栏
Georgewu2 天前
【HarmonyOS组件/模板集成创新活动-如何高效开发鸿蒙应用 (鸿社圈子)】
harmonyos
前端世界2 天前
跨平台 App 如何无痛迁移到鸿蒙系统?全流程实战+Demo 教程
华为·harmonyos
龙儿筝2 天前
鸿蒙和Android知识点
android·harmonyos