背景
在应用开发中,通常需要对ArkUI组件进行封装以便业务复用。结合目前鸿蒙化过程中的实际案例,主要包含以下三种ArkUI组件封装复用的典型业务场景:
- 公用组件封装场景:公用组件封装主要指对系统组件进行封装使用。比如公共组件库需要按照UX规范样式提供统一的系统组件样式供其他业务团队使用,如登录按钮、弹窗按钮。
- 弹窗组件封装场景:弹窗组件内部封装弹窗内容和弹窗控制器,调用方通过状态变量控制弹窗显隐。
- 组件工厂类封装场景:组件工厂类封装了全部的组件并将自身向外暴露,调用方通过传入不同的参数,从组件工厂类中获取对应的组件。
下面,本文将针对以上业务场景,具体说明各场景及其实现方案。
公用组件封装
场景描述
在应用开发过程中,不同的业务场景可能需要使用相同功能和样式的ArkUI组件。例如,登录页面登录按钮和购物页面结算按钮可能样式相同。该场景常用方法是抽取相同样式的逻辑部分,并将其封装成一个自定义组件到公共组件库中。在业务场景开发时,统一从公共组件库获取封装好的公用组件。
以Button组件为例,当多处业务场景需要使用相同样式的Button组件时,将通用逻辑封装成一个MyButton自定义组件,并在通用逻辑中定制了公共的fontSize和fontColor属性。当需要把MyButton组件以Button扩展组件的形式集成到公共组件库中,提供给外部其他团队使用时,为了使它具备Button的所有基础能力并支持以链式调用的方式使用Button组件原生的属性接口,需要在MyButton组件内穷举所有的Button属性 。自定义组件的代码如下
@Component
struct MyButton {
@Prop text: string = '';
@Prop stateEffect: boolean = true;
// ...穷举所有Button独有属性
build() {
Button(this.text)
.fontSize(12)
.fontColor('#FFFFFF')
.stateEffect(this.stateEffect)// stateEffect属性的作用是控制默认点击动画
.xxx //穷举Button其他独有属性赋值
}
}
在使用MyButton 组件时,若需修改组件显示内容text和点击动画效果stateEffect时(其他Button独有的属性用法相同),需要以参数的形式传入:
@Component
struct Index {
build() {
MyButton({ text: '点击带有动效', stateEffect: true, ... }) // 入参包含MyButton 组件中定义的全部 Button独有属性
}
}
当前方案的缺点如下:
- 使用方式和系统组件不一致:系统组件通过链式调用的方式设置组件属性,该方案自定义组件需要以“参数列表”形式设置组件属性。
- 自定义组件入参过大:若需要使用系统组件的全量属性方法,则需在封装的自定义组件中以入参的形式穷举接收每个属性值。在使用自定义组件时,也需将全量的属性值以参数形式传入。
- 不利于后期维护:当自定义组件中的系统组件属性发生变更时,自定义组件也需要同步适配。
实现方案
为解决上述方案缺点,ArkTS为每个系统组件提供了attributeModifier属性方法。该方法将组件属性设置分离到系统提供的AttributeModifier接口实现类实例中,通过自定义Class类实现AttributeModifier接口对系统组件属性进行扩展。通过AttributeModifier实现公用组件有如下两种方案:
方案一:提供方对外提供封装好的自定义组件。
以封装系统组件Button为例,该方案实现步骤如下:
- 提供方在公共组件库中创建公用的自定义组件,该组件支持外部传入attributeModifier属性。
//提供方自定义组件并导出
@Component
export struct MyButton {
@Prop text: string = '';
// 接受外部传入的AttributeModifier类实例
@Prop modifier: AttributeModifi