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控制器,实现调用控制器方法来调用子组件的方法。通过这种方法给子组件封装一些能力,比如数据处理,刷新,动画,发通知等。
具体实现方式如下:
- 定义一个
ChildController
类,在其中定义和子组件中类型相同的方法,例如:
class ChildController {
changeText = (value: string) => { console.log('11111') }
}
export let ChildRef = new ChildController()
在子组件中,将实际封装的方法给到
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); } } }
在父组件中,新建一个
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中实现父组件调用子组件的实现方法,通过松耦合通信方式,解决父组件无法持有子组件直接调用子组件的难题。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。