ArkTs学习之ArkTS装饰器@Styles装饰器 @Extend装饰器, AttributeModifier 机制(三)
在ArkUI的开发过程中,样式的复用和管理对于提升代码的可维护性和开发效率至关重要。为此,ArkUI提供了多种机制来实现样式的复用和扩展,主要包括:@Styles
、@Extend
装饰器,以及AttributeModifier
机制。本文将基于最新的ArkUI版本,详细探讨这三者的应用场景、使用方法及其优缺点。
一. @Styles 装饰器
1. 概述
@Styles
装饰器用于将多条样式设置提炼成一个方法,方便在组件声明时直接调用,实现样式的快速定义和复用。它主要适用于通用属性和事件的复用。
2. 使用规则
- 定义位置:可以在组件内或全局定义。全局定义时,需在方法名前添加
function
关键字;组件内定义时,则不需要。 - 参数支持:
@Styles
方法不支持参数传递。 - 访问组件状态:定义在组件内的
@Styles
方法可以通过this
访问组件的常量和状态变量,并可以在方法内通过事件来改变状态变量的值。 - 访问范围,在全局定义时需在方法名前添加 function 关键字,且只能在当前文件内使用,不支持 export。若想实现 export 功能,推荐使用 AttributeModifier。
3. 示例
以下示例展示了如何在全局和组件内定义和使用@Styles
装饰器:
//🌾:全局定义的@Styles封装的样式 @Styles function globalFancy() { .width(150) .height(100) .backgroundColor(Color.Pink) } @Entry @Component struct FancyUse { /** 成员变量 */ @State heightValue: number = 100 /** 构建函数 */ build() { Column({ space: 10 }) { // 使用全局的@Styles封装的样式 Text('FancyA') .globalFancy() .fontSize(30) // 使用组件内的@Styles封装的样式 Text('FancyB') .fancy() .fontSize(30) } } //🌾:组件内定义的@Styles封装的样式 @Styles fancy() { .width(200) .height(this.heightValue) .backgroundColor(Color.Yellow) .onClick(() => { this.heightValue = 200 }) } }
在上述代码中,globalFancy
是在全局定义的样式方法,而fancy
是在组件内定义的样式方法。需要注意的是,组件内的@Styles
优先级高于全局定义的同名@Styles
。
二. @Extend 装饰器
1. 概述
@Extend
装饰器用于扩展原生组件的样式,支持封装指定组件的私有属性和事件。与@Styles
不同,@Extend
支持参数传递,提供了更大的灵活性。
2. 使用规则
- 定义位置:仅支持在全局定义,不支持在组件内部定义。
- 参数支持:
@Extend
方法支持参数传递,参数可以是函数或状态变量。当状态变量改变时,UI会自动刷新渲染。 - 方法调用:可以在
@Extend
方法内调用其他预定义的@Extend
方法,实现样式的组合和复用。 - 访问范围:同样存在局限性,它也是编译期处理,不支持跨文件的导出复用,不支持 export
3. 示例
以下示例展示了如何使用@Extend
装饰器定义和应用样式:
//🌾:定义一个扩展Text组件的样式方法 @Extend(Text) function fancyText(weightValue: number, color: Color) { .fontStyle(FontStyle.Italic) .fontWeight(weightValue) .backgroundColor(color) } @Entry @Component struct FancyUse { /** 成员变量 */ @State label: string = 'Hello World' /** 构建函数 */ build() { Row({ space: 10 }) { Text(`${this.label}`) .fancyText(100, Color.Blue) Text(`${this.label}`) .fancyText(200, Color.Pink) Text(`${this.label}`) .fancyText(300, Color.Orange) }.margin('20%') } }
在上述代码中,fancyText
方法扩展了Text
组件的样式,并支持通过参数动态设置字体粗细和背景颜色。
三. AttributeModifier 机制
虽然@Styles
和@Extend
装饰器提供了样式复用的能力,但它们存在一些限制:
- 跨文件复用:由于是编译期处理,这些装饰器不支持跨文件的导出和复用。
- 动态属性设置:对于属性的设置,无法支持复杂的业务逻辑,只能通过三元表达式对所有可能设置的属性进行全量设置,效率较低。
为了解决上述问题,ArkUI引入了AttributeModifier
机制。
1. 概述
AttributeModifier
是一种自定义扩展机制,允许开发者在运行时动态地修改组件的属性和样式。它支持跨文件的导出和复用,并且可以包含复杂的业务逻辑,动态决定是否设置某些属性。
2. 使用规则
- 定义:通过实现
AttributeModifier
接口,定义自定义的属性修改器。 - 应用:在组件中,通过
use
方法应用自定义的属性修改器。
3. 应用场景
在需要动态控制组件属性、进行复杂样式逻辑处理以及跨文件共享样式和属性设置时,AttributeModifier 都能大显身手。比如在一个电商应用中,根据商品的不同状态(如热销、新品、折扣等)动态设置商品展示组件的样式和属性。
以下示例展示了如何定义和使用AttributeModifier
:
🦋 示例一:
//🌾:动态改变按钮的颜色:通过自定义 AttributeModifier 类,实现点击按钮时切换背景颜色。 class MyButtonModifier implements AttributeModifier<ButtonAttribute> { isDark: boolean = false applyNormalAttribute(instance: ButtonAttribute): void { instance.backgroundColor(this.isDark ? Color.Black : Color.Red) } } @Component struct attributePressedDemo { /** 成员变量 */ @State modifier: MyButtonModifier = new MyButtonModifier() /** 构建函数 */ build() { Column() { Button('按钮') .attributeModifier(this.modifier) } } }
🦋 示例二:
@Component struct attributeDemo { /** 成员变量 */ @State modifier: MyButtonModifier = new MyButtonModifier() /** 构建函数 */ build() { Column() { Button('按钮') .attributeModifier(this.modifier) .onClick(() => { this.modifier.isDark = !this.modifier.isDark }) } } } //🌾:分别设置普通状态和按下状态颜色:利用 AttributeModifier 提供的 applyPressedAttribute 方法,实现按下按钮时背景颜色变化。 class MyButtonModifier implements AttributeModifier<ButtonAttribute> { applyNormalAttribute(instance: ButtonAttribute): void { instance.backgroundColor(Color.Black) } applyPressedAttribute(instance: ButtonAttribute): void { instance.backgroundColor(Color.Red) } }
四. AttributeModifier 、@Styles 和 @Extend 对比
与 @Styles 和 @Extend 相比,AttributeModifier 具有更强大的能力和灵活性。它可以让开发者动态设置组件的属性,支持在属性设置时使用 if/else 语法,并且能根据需要使用多态样式设置属性。同时,它支持跨文件导出,弥补了 @Styles 和 @Extend 的不足。
能力 | @Styles | @Extend | AttributeModifier |
---|---|---|---|
跨文件导出 | 不支持 | 不支持 | 支持 |
通用属性设置 | 支持 | 支持 | 支持 |
通用事件设置 | 支持 | 支持 | 部分支持 |
组件特有属性设置 | 不支持 | 支持 | 部分支持 |
组件特有事件设置 | 不支持 | 支持 | 部分支持 |
参数传递 | 不支持 | 支持 | 支持 |
多态样式 | 支持 | 不支持 | 支持 |
业务逻辑 | 不支持 | 不支持 | 支持 |
可以看出,与@Styles和@Extend相比,AttributeModifier提供了更强的能力和灵活性,且在持续完善全量的属性和事件设置能力,因此推荐优先使用AttributeModifier。
五. 总结
@Styles 适用于简单的组件样式复用,能提高代码编写效率;@Extend 专注于特定组件的样式扩展;而 AttributeModifier 则以其强大的动态属性设置能力和跨文件支持,在复杂场景下表现出色。在实际开发中,应根据具体需求选择合适的方式,以实现高效、灵活的 ArkUI 应用开发。