HarmonyOS Next 主动调用自定义控件中封装的方法最佳实践

1、背景介绍

HarmonyOS Next主要开发语言是ArkTS,语言框架ArkUI是声明式UI,声明式UI一般不直接操作控件,而是通过状态变量更新来驱动UI刷新。但是有些场景,只通过状态变量驱动UI刷新无法满足我们复杂场景下的业务逻辑,需要在父布局调用子控件中的方法,这种情况怎么处理呢?

2、系统方式参考

系统提供的控件,比如对话框Dialog、计时器控件TextTimer、文本输入控件TextArea等,在构造时要求传入controller,通过controller在父控件中直接调用子控件中的方法。
TextTimerController提供了start、pause、reset方法供父组件调用,CustomDialogController提供了open和close方法供父组件调用,一次来达到操作子组件的效果。

我们可以参考类似思路,为子组件封装Controller供父组件调用。

3、调用子组件方式封装

父组件调用子组件对外提供的Controller控制器,实现调用控制器方法来调用子组件的方法。通过这种方法给子组件封装一些能力,比如数据处理,刷新,动画,发通知等。

具体实现方式如下:

  1. 定义一个ChildController类,在其中定义和子组件中类型相同的方法,例如:
class ChildController { 
    changeText = (value: string) => { console.log('11111') } 
} 
export let ChildRef = new ChildController()
  1. 在子组件中,将实际封装的方法给到controller,在aboutToAppear中,将子组件的方法赋值给controller中的方法变量,以此达到父组件调用Controller方法时实际调用的是子组件的方法。例如:
    ```
    @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);
}
}
}

3. 在父组件中,新建一个`controller`对象然后传入子组件中,在父组件中调用`controller`对应的方法即可。例如:

@Entry
@Component
struct Parent {
private ChildRef = new ChildController();
build() {
Column() {
Text('调用 Child 的 changeText').fontSize('18vp').fontColor(Color.Gray);
Divider();
Child({ controller: this.ChildRef });
}
}
}

```

4、设计方式分析

这种方式的原理主要是通过创建一个中间的 controller 对象来实现间接的通信。在父组件中持有这个 controller 对象,子组件在初始化时将自身的实际方法赋值给 controller 对象中对应的方法引用。这样,当父组件调用 controller 对象的方法时,实际上是在调用子组件中已经赋值过的方法。这实现了一种松耦合的通信方式,避免了父组件直接依赖子组件的内部实现,提高了代码的可维护性和可扩展性。

5、总结

本文介绍了在声明式UI框架ArkUI中实现父组件调用子组件的实现方法,通过松耦合通信方式,解决父组件无法持有子组件直接调用子组件的难题。

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐