DEV Community

Cover image for HarmonyOS Development: How does the parent component call the method in the child component?
程序员一鸣
程序员一鸣

Posted on

HarmonyOS Development: How does the parent component call the method in the 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)
  }
}
Enter fullscreen mode Exit fullscreen mode

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)
  }
}
Enter fullscreen mode Exit fullscreen mode

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)
    }
  }
Enter fullscreen mode Exit fullscreen mode

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)
  }
}
Enter fullscreen mode Exit fullscreen mode

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)
  }
}
Enter fullscreen mode Exit fullscreen mode

method 3: interface callback

defining Callback Functions

class ChangeController {
  change = () => {}
}
Enter fullscreen mode Exit fullscreen mode

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)
  }
}
Enter fullscreen mode Exit fullscreen mode

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)
  }
}
Enter fullscreen mode Exit fullscreen mode

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)
  }
}
Enter fullscreen mode Exit fullscreen mode

trigger Event

@Entry
@Component
struct DemoPage {
  build() {
    Column() {
      Child()
      Button("click")
        .onClick(() => {
          getContext().eventHub.emit('changeUI')
        })
    }
    .height('100%')
    .width('100%')
    .justifyContent(FlexAlign.Center)
  }
}
Enter fullscreen mode Exit fullscreen mode

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.

Top comments (0)