一、@Styles装饰器:组件级样式复用
1. 核心特性
@Styles装饰器是ArkUI框架中实现样式复用的基础工具,支持组件内定义和全局定义两种模式。组件内定义的@Styles方法可以访问组件的状态变量(如@State),而全局定义需添加function
关键字且不支持状态绑定。其优先级遵循组件内样式 > 全局样式 > 原生默认样式。
2. 应用场景
// 全局样式(不支持状态访问)
@Styles function globalStyle() {
.width(150)
.height(100)
.backgroundColor(Color.Pink)
}
@Component struct CustomComponent {
@State private btnHeight: number = 50
// 组件内动态样式
@Styles btnStyle() {
.height(this.btnHeight)
.backgroundColor('#FF4081')
.onClick(() => this.btnHeight = 80)
}
build() {
Column() {
Button('全局样式').globalStyle()
Button('动态样式').btnStyle()
}
}
}
限制:仅支持通用属性/事件,不支持参数传递。
二、@Extend装饰器:组件能力扩展
1. 核心优势
@Extend装饰器通过参数化配置和私有属性支持实现组件扩展。其特点包括:
- 支持目标组件的私有属性(如Text的
fontColor
) - 允许传递函数参数实现事件绑定
- 支持链式调用组合多个扩展方法。
2. 典型应用
// 扩展Text组件样式
@Extend(Text)
function highlightText(size: number, color: Color) {
.fontSize(size)
.fontColor(color)
.textShadow({ radius: 2, color: Color.Black })
}
// 带事件处理的扩展
@Extend(Button)
function animatedButton(onClick: () => void) {
.scale({ x: 0.95, y: 0.95 })
.onClick(onClick)
}
// 使用示例
Text('重要提示').highlightText(24, Color.Red)
Button('提交').animatedButton(() => submitForm())
三、stateStyles:动态状态响应
1. 状态类型体系
状态类型 | 触发条件 | 典型组件 |
---|---|---|
normal | 默认状态 | 所有组件 |
pressed | 按压状态(触摸/鼠标按下) | Button |
focused | 获焦状态(Tab键导航) | TextInput |
disabled | 禁用状态 | Switch/Button |
selected | 选中状态 | TabBar/Checkbox |
2. 实现方案
@Component struct StatefulComponent {
@Styles pressedStyle() {
.backgroundColor('#FF5252')
.scale({ x: 0.95, y: 0.95 })
}
build() {
Button('动态按钮')
.stateStyles({
normal: {
.backgroundColor('#2196F3')
},
pressed: this.pressedStyle,
disabled: {
.opacity(0.5)
.backgroundColor('#BDBDBD')
}
})
}
}
进阶技巧:与@State变量联动实现动态样式切换。
四、@AnimatableExtend:动画属性扩展
1. 实现原理
通过实现AnimatableArithmetic
接口定义数值运算规则,使不可动画属性(如Polyline的points)支持动画效果。
2. 开发实践
// 自定义动画向量类型
class Vector2D implements AnimatableArithmetic<Vector2D> {
x: number = 0
y: number = 0
plus(rhs: Vector2D): Vector2D {
return new Vector2D(this.x + rhs.x, this.y + rhs.y)
}
// 实现其他运算符...
}
// 扩展Polyline组件
@AnimatableExtend(Polyline)
function animPath(points: Vector2D[]) {
.points(points.map(p => [p.x, p.y]))
}
@Component struct PathAnimation {
@State path: Vector2D[] = [new Vector2D(0,0), new Vector2D(100,100)]
build() {
Polyline()
.animPath(this.path)
.animation({ duration: 2000, curve: Curve.EaseInOut })
.onClick(() => {
this.path = [new Vector2D(200,50), new Vector2D(300,200)]
})
}
}
适用场景:路径动画、颜色渐变、自定义布局动画。
五、对比
特性 | @Styles | @Extend | stateStyles | @AnimatableExtend |
---|---|---|---|---|
核心目的 | 样式复用 | 组件扩展 | 状态响应 | 动画扩展 |
定义位置 | 组件/全局 | 全局 | 组件内 | 全局 |
参数支持 | ❌ | ✅ | ❌ | ✅ |
状态感知 | 组件内样式支持 | ❌ | ✅ | ❌ |
动画支持 | ❌ | ❌ | ❌ | ✅ |
私有属性访问 | ❌ | ✅ | ❌ | ✅ |
六、总结
- 基础样式(@Styles) :定义全局基础样式(如按钮尺寸、字体规范)
- 组件扩展(@Extend) :创建组件变体(如带图标的按钮)
- 状态样式(stateStyles) :处理交互状态(按压/禁用样式)
- 动画扩展(@AnimatableExtend):实现复杂动效
性能优化建议
- 避免在@Styles中进行复杂计算
- stateStyles建议使用纯数值状态变量
- 优先使用系统内置动画属性,必要时再使用自定义动画
综合示例
// 样式分层架构
@Styles function baseButton() {
.padding(10).borderRadius(5)
}
@Extend(Button)
function primaryButton() {
baseButton()
.backgroundColor(BrandColor.Primary)
.stateStyles({
pressed: {
.opacity(0.8)
}
})
}
// 实现动画按钮
@AnimatableExtend(Button)
function scaleButton(scale: number) {
.scale({ x: scale, y: scale })
}
@Entry
@Component struct SmartButtonPage {
@State btnScale: number = 1
build() {
Column() {
Button('智能按钮')
.primaryBtn()
.scaleButton(this.btnScale)
.animation({ curve: Curve.Spring })
.onClick(() => {
this.btnScale = this.btnScale > 1 ? 1 : 1.2
})
}
}
}