一、@Styles裝飾器:組件級樣式復(fù)用
1. 核心特性
@Styles裝飾器是ArkUI框架中實現(xiàn)樣式復(fù)用的基礎(chǔ)工具,支持組件內(nèi)定義和全局定義兩種模式。組件內(nèi)定義的@Styles方法可以訪問組件的狀態(tài)變量(如@State),而全局定義需添加function
關(guān)鍵字且不支持狀態(tài)綁定。其優(yōu)先級遵循組件內(nèi)樣式 > 全局樣式 > 原生默認樣式。
2. 應(yīng)用場景
// 全局樣式(不支持狀態(tài)訪問)
@Styles function globalStyle() {
.width(150)
.height(100)
.backgroundColor(Color.Pink)
}
@Component struct CustomComponent {
@State private btnHeight: number = 50
// 組件內(nèi)動態(tài)樣式
@Styles btnStyle() {
.height(this.btnHeight)
.backgroundColor('#FF4081')
.onClick(() => this.btnHeight = 80)
}
build() {
Column() {
Button('全局樣式').globalStyle()
Button('動態(tài)樣式').btnStyle()
}
}
}
限制:僅支持通用屬性/事件,不支持參數(shù)傳遞。
二、@Extend裝飾器:組件能力擴展
1. 核心優(yōu)勢
@Extend裝飾器通過參數(shù)化配置和私有屬性支持實現(xiàn)組件擴展。其特點包括:
- 支持目標(biāo)組件的私有屬性(如Text的
fontColor
) - 允許傳遞函數(shù)參數(shù)實現(xiàn)事件綁定
- 支持鏈?zhǔn)秸{(diào)用組合多個擴展方法。
2. 典型應(yīng)用
// 擴展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:動態(tài)狀態(tài)響應(yīng)
1. 狀態(tài)類型體系
狀態(tài)類型 | 觸發(fā)條件 | 典型組件 |
---|---|---|
normal | 默認狀態(tài) | 所有組件 |
pressed | 按壓狀態(tài)(觸摸/鼠標(biāo)按下) | Button |
focused | 獲焦?fàn)顟B(tài)(Tab鍵導(dǎo)航) | TextInput |
disabled | 禁用狀態(tài) | Switch/Button |
selected | 選中狀態(tài) | TabBar/Checkbox |
2. 實現(xiàn)方案
@Component struct StatefulComponent {
@Styles pressedStyle() {
.backgroundColor('#FF5252')
.scale({ x: 0.95, y: 0.95 })
}
build() {
Button('動態(tài)按鈕')
.stateStyles({
normal: {
.backgroundColor('#2196F3')
},
pressed: this.pressedStyle,
disabled: {
.opacity(0.5)
.backgroundColor('#BDBDBD')
}
})
}
}
進階技巧:與@State變量聯(lián)動實現(xiàn)動態(tài)樣式切換。
四、@AnimatableExtend:動畫屬性擴展
1. 實現(xiàn)原理
通過實現(xiàn)AnimatableArithmetic
接口定義數(shù)值運算規(guī)則,使不可動畫屬性(如Polyline的points)支持動畫效果。
2. 開發(fā)實踐
// 自定義動畫向量類型
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)
}
// 實現(xiàn)其他運算符...
}
// 擴展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 |
---|---|---|---|---|
核心目的 | 樣式復(fù)用 | 組件擴展 | 狀態(tài)響應(yīng) | 動畫擴展 |
定義位置 | 組件/全局 | 全局 | 組件內(nèi) | 全局 |
參數(shù)支持 | ? | ? | ? | ? |
狀態(tài)感知 | 組件內(nèi)樣式支持 | ? | ? | ? |
動畫支持 | ? | ? | ? | ? |
私有屬性訪問 | ? | ? | ? | ? |
六、總結(jié)
- 基礎(chǔ)樣式(@Styles) :定義全局基礎(chǔ)樣式(如按鈕尺寸、字體規(guī)范)
- 組件擴展(@Extend) :創(chuàng)建組件變體(如帶圖標(biāo)的按鈕)
- 狀態(tài)樣式(stateStyles) :處理交互狀態(tài)(按壓/禁用樣式)
- 動畫擴展(@AnimatableExtend):實現(xiàn)復(fù)雜動效
性能優(yōu)化建議
- 避免在@Styles中進行復(fù)雜計算
- stateStyles建議使用純數(shù)值狀態(tài)變量
- 優(yōu)先使用系統(tǒng)內(nèi)置動畫屬性,必要時再使用自定義動畫
綜合示例
// 樣式分層架構(gòu)
@Styles function baseButton() {
.padding(10).borderRadius(5)
}
@Extend(Button)
function primaryButton() {
baseButton()
.backgroundColor(BrandColor.Primary)
.stateStyles({
pressed: {
.opacity(0.8)
}
})
}
// 實現(xiàn)動畫按鈕
@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
})
}
}
}