之前的文章中介绍过Styles和Extend对基础组件的属性封装,可以节省相同组件设置相同属性的代码量,也方便统一修改管理。然而也有自己的局限性,如果在不同的文件中则不能引用。
细心的同学可能会发现,手势系列文章旋转手势、快滑手势、组合手势文章中都使用了Radio组件测试,使用了Extend封装基础属性。并且名字都不同,这是为什么呢?
例如我在多个文件中定义了相同的Radio属性方法:
@Extend(Radio)
function myRadioStyle() {
.checked(false)
.radioStyle({
checkedBackgroundColor: Color.Green, //开启状态底板颜色
uncheckedBorderColor:Color.Red, //关闭状态描边颜色
indicatorColor:Color.Yellow //开启状态内部圆饼颜色
})
.height(20)
.width(20)
}
由于@Extend不支持export,所以编译时,会出现以下错误:
ERROR: ArkTS:ERROR File:
D:/.../SwipeGestureTest.ets:2:10
Duplicate function implementation.
如果使用相同的方法名,会提示方法重复实现
当我们在多个地方需要使用相同样式的组件时,我们不能每个页面都重新定义一遍,这样不仅代码冗余,如果需要修改,也是很大的工作量。因此,需要将使用频繁或者公用的属性抽离封装出来,统一修改使用。
解决以上问题,需要使用属性修改器(AttributeModifier)
首先看一下@Styles、@Extend和AttributeModifier的主要区别
| 能力 | @Styles | @Extend | AttributeModifier |
|---|---|---|---|
| 跨文件导出 | 不支持 | 不支持 | 支持 |
| 通用属性设置 | 支持 | 支持 | 支持 |
| 参数传递 | 不支持 | 支持 | 支持 |
| 多态样式 | 支持 | 不支持 | 支持 |
| 业务逻辑 | 不支持 | 不支持 | 支持 |
实现全局的通用属性设置,主要依靠AttributeModifier支持跨文件导出能力。@Styles和@Extend均是编译期处理,不支持跨文件的导出复用。
AttributeModifier是一个接口,T必须指定为组件对应的Attribute类型,或者是CommonAttribute。
declare interface AttributeModifier<T> {
//组件普通状态时的样式
applyNormalAttribute?(instance: T): void;
//组件按压状态的样式
applyPressedAttribute?(instance: T): void;
//组件获焦状态的样式
applyFocusedAttribute?(instance: T): void;
//组件禁用状态的样式
applyDisabledAttribute?(instance: T): void;
//组件选中状态的样式
applySelectedAttribute?(instance: T): void;
}
接下来以实现全局Radio属性为例介绍:
1.新建一个class 实现 AttributeModifier,传入泛型RadioAttribute
2.实现applyNormalAttribute方法,只需设置默认状态的样式即可
3.自定义参数,设置默认是否选中
4.将Extend的属性设置复制到applyNormalAttribute中实现。
export class MyRadioModifier implements AttributeModifier<RadioAttribute> {
private isChecked:boolean = false
constructor(checkd:boolean = false) {
this.isChecked = checkd
}
//组件普通状态时的样式
applyNormalAttribute(instance: RadioAttribute): void {
instance
.checked(this.isChecked)
.radioStyle({
checkedBackgroundColor: Color.Green, //开启状态底板颜色
uncheckedBorderColor:Color.Red, //关闭状态描边颜色
indicatorColor:Color.Yellow //开启状态内部圆饼颜色
})
.height(20)
.width(20)
}
}
使用方法:
@Local myRadioStyle:MyRadioModifier = new MyRadioModifier()
Radio({ value: 'r1', group: 'radioGroup' })
.attributeModifier(new MyRadioModifier(true))
.onChange((isChecked: boolean) => {
})
Radio({ value: 'r2', group: 'radioGroup' })
.attributeModifier(this.myRadioStyle)
.onChange((isChecked: boolean) => {
})
以上就可以在任何文件中使用Radio的设置属性了。
注意:
1.一个组件上同时使用属性方法和applyNormalAttribute设置相同的属性,遵循属性覆盖原则,即后设置的属性生效。
2.一个Modifier实例对象可以在多个组件上使用。
3.一个组件上多次使用applyNormalAttribute设置不同的Modifier实例,同样遵循属性覆盖原则。