鸿蒙开发 – 自定义组件 和 组件通信的方法 (15:02 刚刚更新了动图,嘿嘿)

自定义组件的基本结构

@Entry @Component struct MyComponent {   build(){      // ...   } } 
  • build()函数

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

build() {   Column() {     Text('测试')     Button('点击')   } } 
  • struct 关键字

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

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

struct MyComponent { } 
  • @Component 装饰器

@Component 用来声明一个组件

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

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

@Entry @Component struct MyComponent {   build() {   } } 

组件通信

父子间单向传递 @Prop

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

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

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

  • 父组件
import Child from './Child'  @Entry @Component struct Parent {   @State text: string = '123'    build() {     Column() {       Text(`我是父组件,文本内容:${this.text}`)       Button(`更新按钮`)         .onClick(() => {           this.text = '456'         })        Child({ text: this.text })         .margin({top: 50})     }     .width('100%')   } } 
  • 子组件

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

@Component export default struct Child {   @Prop text: string = ''    build() {     Row() {       Text(`我是子组件,父组件传过来的内容:${this.text}`)     }   } } 

效果如下:

鸿蒙开发 - 自定义组件 和 组件通信的方法 (15:02 刚刚更新了动图,嘿嘿)

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

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

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

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

// 子组件  @Component export default struct Child {   @Link text: string    build() {     Column() {       Text(`我是子组件,父组件传过来的内容:${this.text}`)        Button('更改父组件传过来的数据')         .onClick(() => {           this.text = '789'         })     }   } } 

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

鸿蒙开发 - 自定义组件 和 组件通信的方法 (15:02 刚刚更新了动图,嘿嘿)

子组件调用父组件的方法

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

  • 父组件

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

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 函数,调用即可

@Component export default struct Child {   parentClick?: () => void    build() {     Column() {       Button('我是子组件,点击')         .onClick(() => {           if (this.parentClick) {             this.parentClick()           }         })     }   } } 

效果如下:

鸿蒙开发 - 自定义组件 和 组件通信的方法 (15:02 刚刚更新了动图,嘿嘿)

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

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

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

@Provide text: string = '123' 

后代组件使用 @Consume 接收

@Consume text: string 

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

eventHub 事件总线

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

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

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

@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}`)   } } 

效果如下:

鸿蒙开发 - 自定义组件 和 组件通信的方法 (15:02 刚刚更新了动图,嘿嘿)

方法
  • on(event: string, callback: Function) 监听事件
  • emit(event: string, ...args: Object[]) 触发事件
  • off(event: string, callback?: Function) 取消订阅的指定事件
    • 传入 callback:取消指定的 callback 对指定事件的订阅,当该事件触发后,将不会再回调该callback。
    • 不传 callback:取消所有 callback 对指定事件的订阅。
发表评论

相关文章