DEV Community

Cover image for HarmonyOS Next Best Practices for Actively Invoking Methods Encapsulated in Custom Control
kouwei qing
kouwei qing

Posted on

HarmonyOS Next Best Practices for Actively Invoking Methods Encapsulated in Custom Control

HarmonyOS Next Best Practices for Actively Invoking Methods Encapsulated in Custom Controls

1. Background Introduction

The primary development language for HarmonyOS Next is ArkTS, and its framework ArkUI is a declarative UI. Declarative UIs typically do not manipulate controls directly but drive UI refreshes through state variable updates. However, in some scenarios, state-driven UI refreshes cannot meet complex business logic, requiring parent layouts to invoke methods in child controls. How to handle this?

2. Reference to System Approaches

System-provided controls like Dialog, TextTimer, and TextArea require a controller during construction, allowing parent controls to directly invoke child control methods via the controller:

  • TextTimerController provides start, pause, and reset methods for parent components.
  • CustomDialogController provides open and close methods for parent components.

We can adopt a similar approach: encapsulate a controller for child components to enable parent-component invocation.

3. Encapsulation of Child Component Invocation

The parent component invokes methods of the child component by calling a controller exposed by the child component. This encapsulates capabilities like data processing, refreshing, animations, and notifications.

Implementation Steps:

  1. Define a ChildController class with methods matching those in the child component:
class ChildController { 
  changeText = (value: string) => { console.log('11111') } 
} 
export let ChildRef = new ChildController()
Enter fullscreen mode Exit fullscreen mode
  1. In the child component, assign actual methods to the controller. In aboutToAppear, map the child component's methods to the controller's method variables:
@Component
struct Child {
  @State private text: string = '初始值';
  private controller: ChildController = new ChildController();

  aboutToAppear() {
    if (this.controller) {
      this.controller.changeText = this.changeText;
    }
    console.log('aaa');
  }

  private changeText = (value: string) => {
    this.text = value;
    console.log('bbb');
  }

  build() {
    Column() {
      Text(this.text);
    }
  }
}
Enter fullscreen mode Exit fullscreen mode
  1. In the parent component, create a controller object, pass it to the child component, and invoke the controller's methods:
@Entry
@Component
struct Parent {
  private ChildRef = new ChildController();
  build() {
    Column() {
      Text('调用 Child 的 changeText').fontSize('18vp').fontColor(Color.Gray);
      Divider();
      Child({ controller: this.ChildRef });
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

4. Design Analysis

This approach uses an intermediate controller object for indirect communication:

  • The parent component holds the controller, while the child component assigns its actual methods to the controller during initialization.
  • When the parent component invokes the controller's methods, it effectively calls the child component's methods.
  • This achieves loose coupling, avoiding direct parent dependency on child component internals, and enhances code maintainability and extensibility.

5. Summary

This article introduces a method for parent components to invoke child components in the declarative UI framework ArkUI. Through loose-coupling communication, it solves the challenge of parent components directly invoking child component methods without holding direct references.

Top comments (0)