HarmonyOS Development: How a Parent Component Calls a Method in a Child Component

Foreword
this article is based on Api13
in many scenarios, the parent component needs to trigger a method in the child component to implement some specific logic, but ArkUI is a declarative UI and cannot directly call the method in the child component, so how to implement this function?
To give a very common case, you can update the sub-component UI by calling a method in the sub-component. The simple code is as follows. Only by calling the changeUI method can the UI update be triggered.
@Component
struct Child {
@State message: string = "I am child"
/**
*AUTHOR:AbnerMing
*INTRODUCE:
*/
changeUI() {
this.message = "child UI updata"
}
build() {
Text(this.message)
.width("100%")
.height(50)
.backgroundColor(Color.Pink)
.textAlign(TextAlign.Center)
}
}
Method 1: @ Watch decorator
if you are using the V1 version decorator, we can easily implement it using the @ Watch decorator.
Sub-component definition @ Watch decorator
@Component
struct Child {
@State message: string = "I am child"
@Prop @Watch("changeUI") isChangeStatus: boolean = false
/**
*AUTHOR:AbnerMing
*INTRODUCE:
*/
changeUI() {
this.message = "child UI updata"
}
build() {
Text(this.message)
.width("100%")
.height(50)
.backgroundColor(Color.Pink)
.textAlign(TextAlign.Center)
}
}
parent component calls
the isChangeStatus attribute defined by the child component can be used to continuously change its value.
@Entry
@Component
struct DemoPage {
@State isChangeStatus: boolean = false
build() {
Column() {
Child({ isChangeStatus: this.isChangeStatus })
Button("click")
.onClick(() => {
this.isChangeStatus = !this.isChangeStatus
})
}
.height('100%')
.width('100%')
.justifyContent(FlexAlign.Center)
}
}
Method 2: @ Monitor decorator
it is the same as the implementation of Mode 1, except that the @ Monitor decorator is V2 version, that is, if you are using V2 version decorator, you can use this.
Subcomponent definition @ Monitor decorator
@ComponentV2
struct Child {
@Local message: string = "I am child"
@Param isChangeStatus: boolean = false
/**
*AUTHOR:AbnerMing
*INTRODUCE:child method
*/
@Monitor("isChangeStatus")
changeUI() {
this.message = "child UI updata"
}
build() {
Text(this.message)
.width("100%")
.height(50)
.backgroundColor(Color.Pink)
.textAlign(TextAlign.Center)
}
}
parent component calls
@Entry
@ComponentV2
struct DemoPage {
@Local isChangeStatus: boolean = false
build() {
Column() {
Child({ isChangeStatus: this.isChangeStatus })
Button("click")
.onClick(() => {
this.isChangeStatus = !this.isChangeStatus
})
}
.height('100%')
.width('100%')
.justifyContent(FlexAlign.Center)
}
}
method 3: interface callback
defining Callback Functions
class ChangeController {
change = () => {}
}
child Component Implementation Callback
@Component
struct Child {
@State message: string = "I am child"
changeController: ChangeController = new ChangeController()
aboutToAppear(): void {
if (this.changeController.change != undefined) {
this.changeController.change = () => {
this.changeUI()
}
}
}
/**
*AUTHOR:AbnerMing
*INTRODUCE:child method
*/
changeUI() {
this.message = "child UI updata"
}
build() {
Text(this.message)
.width("100%")
.height(50)
.backgroundColor(Color.Pink)
.textAlign(TextAlign.Center)
}
}
parent component calls function
@Entry
@Component
struct DemoPage {
changeController: ChangeController = new ChangeController()
build() {
Column() {
Child({ changeController: this.changeController })
Button("click")
.onClick(() => {
this.changeController.change()
})
}
.height('100%')
.width('100%')
.justifyContent(FlexAlign.Center)
}
}
method 4: Event subscription EventHub
Subscribe to events
@Component
struct Child {
@State message: string = "I am child"
aboutToAppear(): void {
getContext().eventHub.on("changeUI", ()=>{
this.changeUI()
})
}
/**
*AUTHOR:AbnerMing
*INTRODUCE:child
*/
changeUI() {
this.message = "child UI updata"
}
build() {
Text(this.message)
.width("100%")
.height(50)
.backgroundColor(Color.Pink)
.textAlign(TextAlign.Center)
}
}
trigger Event
@Entry
@Component
struct DemoPage {
build() {
Column() {
Child()
Button("click")
.onClick(() => {
getContext().eventHub.emit('changeUI')
})
}
.height('100%')
.width('100%')
.justifyContent(FlexAlign.Center)
}
}
related Summary
perhaps you may have doubts. It is not enough to directly trigger the sub-component update UI by the decorator. I hope you can understand that the above is only a simple case. In actual development, there may be a lot of logic in the sub-component method, such as network requests, such as data storage, etc., which is not a simple UI update.
Of course, the implementation method cited is not complete, and there may be other ways to implement it. You can choose the appropriate one in the actual development.
Subscribe to my newsletter
Read articles from AbnerMing directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
