
鸿蒙5样式复用指南:@Styles与@Extend装饰器深度解析
样式复用核心概念对比
特性 @Styles装饰器 @Extend装饰器
作用范围 组件内部/跨组件 全局/跨组件
复用单位 组合样式属性 扩展组件能力
参数支持 支持参数传递 不支持参数
状态管理 可访问组件状态 无状态
适用场景 局部通用样式 全局基础组件扩展
性能影响 中等 较低
@Styles装饰器详解
基础用法:组件内部样式复用
@Component
struct ButtonComponent {
// 定义可复用样式
@Styles primaryButtonStyle() {
.backgroundColor(‘#256BFE’)
.borderRadius(8)
.padding(12)
.fontColor(‘#FFFFFF’)
.fontSize(16)
.fontWeight(FontWeight.Medium)
.stateEffect(true)
}
build() {
Column() {
Button(‘主要按钮’)
.primaryButtonStyle() // 应用样式
Button('操作按钮')
.primaryButtonStyle()
.backgroundColor('#10B981') // 扩展样式
}
}
}
带参数的@Styles
@Component
struct CardComponent {
// 参数化样式
@Styles cardStyle(bgColor: string, elevation: number) {
.backgroundColor(bgColor)
.borderRadius(12)
.shadow({ radius: elevation, color: ‘#00000020’ })
.padding(16)
.margin({ bottom: 16 })
}
build() {
Column() {
// 应用带参数的样式
Column() {
Text(‘普通卡片’)
}
.cardStyle(‘#FFFFFF’, 8)
Column() {
Text('高亮卡片')
}
.cardStyle('#FFF9F0', 16)
}
}
}
状态驱动样式
@Component
struct ToggleItem {
@State isActive: boolean = false
// 基于状态的样式
@Styles itemStyle() {
.backgroundColor(this.isActive ? ‘#EBF5FF’ : ‘#FFFFFF’)
.borderColor(this.isActive ? ‘#256BFE’ : ‘#EAECF0’)
.padding(12)
}
build() {
Touchable()
.onClick(() => this.isActive = !this.isActive)
{
Text(‘选项内容’)
.itemStyle() // 应用响应式样式
}
}
}
@Extend装饰器详解
全局组件扩展
// 全局样式文件: globalStyles.ets
// 扩展Text组件
@Extend(Text) function primaryTitle() {
.fontColor(‘#1F2A37’)
.fontSize(20)
.fontWeight(FontWeight.Bold)
.margin({ bottom: 8 })
}
// 扩展Button组件
@Extend(Button) function roundedButton() {
.borderRadius(24)
.padding({
left: 24,
right: 24,
top: 12,
bottom: 12
})
.fontSize(16)
.fontWeight(FontWeight.Medium)
}
复杂样式组合
@Extend(Column) funciton cardLayout() {
.backgroundColor(‘#FFFFFF’)
.borderRadius(12)
.shadow({ radius: 8, color: ‘#00000010’ })
.padding(16)
.margin({ bottom: 16 })
}
// 组合使用多个@Extend
@Extend(Text) function cardTitle() {
.primaryTitle() // 使用已定义的primaryTitle
.fontSize(18) // 覆盖原有尺寸
.margin({ bottom: 12 })
}
@Component
struct ProductCard {
build() {
Column()
.cardLayout() // 应用卡片布局
{
Text(‘商品名称’)
.cardTitle()
// 其他内容...
}
}
}
高级技巧与应用场景
场景1:主题系统实现
// theme.ets - 主题定义文件
export class AppTheme {
static primaryColor: string = ‘#256BFE’
static secondaryColor: string = ‘#10B981’
static textPrimary: string = ‘#1F2A37’
// 文字样式扩展
@Extend(Text) static titleStyle() {
.fontColor(AppTheme.textPrimary)
.fontSize(24)
}
// 按钮基础样式
@Extend(Button) static buttonBase() {
.borderRadius(8)
.padding(12)
.fontSize(16)
.stateEffect(true)
}
}
// 组件中使用
Button(‘主题按钮’)
.buttonBase()
.backgroundColor(AppTheme.primaryColor)
场景2:响应式样式
@Component
struct ResponsiveComponent {
@StorageProp(‘windowWidth’) winWidth: number = 0
// 响应式样式
@Styles cardPadding() {
if (this.winWidth < 600) {
.padding(12)
} else {
.padding(24)
}
}
build() {
Column()
.cardPadding()
{
// 内容区域
}
.onResize((size: Size) => {
this.winWidth = size.width
})
}
}
场景3:企业级UI库封装
// UI库组件基础
@Extend(Button) function baseButton() {
.minWidth(100)
.minHeight(44)
.stateEffect({
pressed: { scale: 0.98 }
})
}
// 预设样式变体
@Styles function primaryVariant() {
.backgroundColor(‘#256BFE’)
.fontColor(‘#FFFFFF’)
}
@Styles function secondaryVariant() {
.backgroundColor(‘#F0F5FF’)
.fontColor(‘#256BFE’)
}
// 实际按钮组件
@Component
export struct CustomButton {
@Prop variant: ‘primary’ | ‘secondary’ = ‘primary’
build() {
Button()
.baseButton()
.if(this.variant === ‘primary’, primaryVariant)
.if(this.variant === ‘secondary’, secondaryVariant)
}
}
性能优化策略
- 样式层级优化
// 避免深层嵌套
@Styles function complexStyle() {
.width(100)
.height(100)
// 其他样式…
}
// 推荐做法:分解为多个基础样式
@Styles function baseSize() {
.width(100)
.height(100)
}
@Styles function specialEffect() {
.shadow({ radius: 8 })
.opacity(0.95)
}
// 组件中组合使用
Component()
.baseSize()
.specialEffect()
2. 按需加载样式
// 动态样式加载
function loadStyles(condition: boolean) {
if (condition) {
return specialStyle;
}
return baseStyle;
}
Component()
.apply(loadStyles(this.useSpecialStyle))
最佳实践指南
- 样式组织原则
resources/
base/
element/
color.json
font.json
styles/
typography.ets // 文字样式
buttons.ets // 按钮扩展
cards.ets // 卡片样式
theme.ets // 主题定义 - 命名规范建议
样式类型 命名模式 示例
基础组件扩展 组件名+基础作用 buttonBase
功能样式 function+描述 cardShadow
变体样式 variant+状态 primaryPressed
响应式样式 属性名+Responsive paddingResponsive
动画样式 animate+效果名 animateFadeIn - 组合使用模式
// 使用@Extend定义基础组件
@Extend(Text) function bodyText() {
.fontSize(16)
.fontColor(‘#4B5563’)
}
// 使用@Styles创建复合样式
@Styles function calloutStyle() {
.bodyText() // 基础文本样式
.backgroundColor(‘#F0F5FF’)
.padding(16)
.borderRadius(8)
}
// 在组件中应用
Component()
.calloutStyle()
常见问题解决方案
问题:样式覆盖冲突
// 方案:使用样式优先级排序
@Styles highPriorityStyle() {
.width(200).priority(‘high’) // 设置高优先级
}
@Styles lowPriorityStyle() {
.width(100)
}
Component()
.highPriorityStyle()
.lowPriorityStyle() // 最终宽度为200
问题:主题切换动态更新
// 主题管理器
class ThemeManager {
static currentTheme: Theme = lightTheme;
// 更新所有带@Extend的样式
static updateTheme(newTheme: Theme) {
this.currentTheme = newTheme;
// 强制刷新依赖主题的样式
AppStorage.setOrCreate(‘themeUpdate’, Date.now());
}
}
// 响应式主题组件
@Extend(Component) function themedBackground() {
.backgroundColor(AppStorage.get<number>(‘themeUpdate’),
() => ThemeManager.currentTheme.background)
}
结语
鸿蒙5的@Styles和@Extend装饰器为样式复用提供了强大的解决方案:
@Styles最佳适用场景:
组件内部样式封装
响应式动态样式
参数化样式变体
@Extend核心优势:
全局组件扩展
UI基础库构建
主题系统实现
通过合理运用这两种机制,开发者可以:
减少70%的样式重复代码
实现统一的UI设计系统
轻松维护多主题适配
快速构建企业级UI库
掌握样式复用的艺术,将大幅提升鸿蒙应用的开发效率和视觉一致性,为构建高质量的应用程序打下坚实基础。
