自定义组件的基本结构
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
用来声明一个组件
@Component
和struct
两者配对使用@Component
只能装饰struct
关键字声明的数据结构
typescript
@Component
struct MyComponent {
build() {
}
}
- @Entry 装饰器
使用 @Entry
用于标记一个页面的入口点。当用户打开应用或导航路由的时候,展示的就是这个组件
typescript
@Entry
@Component
struct MyComponent {
build() {
}
}
组件通信
父子间单向传递 @Prop
@Prop
单向传递数据:父组件数据变化,会通知子组件,但子组件数据变化,不会通知父组件
- 子组件深拷贝父组件传过来的数据,父组件发生数据变更,子组件会跟着变化
- 子组件也可以自己更新数据,但不会同步父组件数据
举例:父组件向子组件传递一个数据 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
双向传递数据:父组件发生数据变化,会通知子组件,同时子组件数据变化,也会通知父组件
使用 @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 对指定事件的订阅。