AttributeModifier
1、AttributeModifier的优点
声明式语法引入了@Styles
和@Extend
两个装饰器,可以解决部分复用的问题,但是存在以下受限场景:
- @Styles和@Extend均是编译期处理,不支持跨文件的导出复用。
- @Styles仅能支持通用属性、事件,不支持组件特有的属性。
- @Styles虽然支持在多态样式下使用,但不支持传参,无法对外开放一些属性。
- @Extend虽然能支持特定组件的私有属性、事件,但同样不支持跨文件导出复用。
- @Styles、@Extend对于属性设置,无法支持业务逻辑编写,动态决定是否设置某些属性。只能通过三元表达式对所有可能设置的属性进行全量设置,设置大量属性时效率低下。
AttributeModifier可以让开发者动态设置组件的属性,支持开发者在属性设置时使用if/else语法,且根据需要使用多态样式设置属性。
与@Styles和@Extend相比,AttributeModifier的能力和灵活性更好。当前持续在构建全量的属性、事件设置能力,推荐使用。
2、AttributeModifier的使用案例
2.1 动态改变按钮的颜色
点击按钮,切换按钮的背景颜色。
//自定义动态属性
class MyButtonModifier implements AttributeModifier<ButtonAttribute> {
isDark: boolean = false
applyNormalAttribute(instance: ButtonAttribute): void {
if (this.isDark) {
instance.backgroundColor(Color.Black)
} else {
instance.backgroundColor(Color.Red)
}
}
}
struct attributeDemo {
modifier: MyButtonModifier = new MyButtonModifier()
build() {
Row() {
Column() {
Button("Button")
//设置动态属性
.attributeModifier(this.modifier)
.onClick(() => {
this.modifier.isDark = !this.modifier.isDark
})
}
.width('100%')
}
.height('100%')
}
}
2.2、分别设置普通状态和按下状态颜色
AttributeModifier
提供了applyPressedAttribute
组件方法,让我们在按下按钮时改变控件的样式,比如按下按钮时背景颜色是红色,松开时变黑色:
class MyButtonModifier implements AttributeModifier<ButtonAttribute> {
//正常状态是黑色
applyNormalAttribute(instance: ButtonAttribute): void {
instance.backgroundColor(Color.Black)
}
//点击是变红色
applyPressedAttribute(instance: ButtonAttribute): void {
instance.backgroundColor(Color.Red)
}
}
struct attributePressedDemo {
modifier: MyButtonModifier = new MyButtonModifier()
build() {
Row() {
Column() {
Button("Button")
.attributeModifier(this.modifier)
}
.width('100%')
}
.height('100%')
}
}
AttributeModifier在开发过程中可以用来优化UI,详见UI组件性能优化
3、性能优化的利器
当需要给自定义组件设置较多属性时,推荐使用自定义AttributeModifier的方式来动态设置自定义组件的属性,减少节点数量的同时,也避免了参数过多导致耗时的问题,具体优化示例如下所示:
// 使用动态属性设置时,需要继承AttributeModifier,自行实现一个Modifier,然后设置到需要的组件上
class ColumnModifier implements AttributeModifier<ColumnAttribute> {
width: number = 0;
height: number = 0;
backgroundColor: ResourceColor | undefined = undefined;
applyNormalAttribute(instance: ColumnAttribute): void {
instance.width(this.width);
instance.height(this.height);
instance.backgroundColor(this.backgroundColor);
}
}
struct CustomComponentModifier {
modifier: ColumnModifier = new ColumnModifier();
aboutToAppear(): void {
this.modifier.width = 100;
this.modifier.height = 100;
this.modifier.backgroundColor = Color.Red;
}
build() {
Column() {
ModifierCustom({ modifier: this.modifier })
}
}
}
struct ModifierCustom {
modifier: AttributeModifier<ColumnAttribute>;
build() {
Column() {
Text('Hello Word')
}.attributeModifier(this.modifier)
}
}