这是一个使用鸿蒙技术开发的本地原生记账应用,非常适合大家用来练手。相关源码已上传至 Github,点击此处查看项目。欢迎大家交流、指正,也欢迎提交 PR。
一、引言
在鸿蒙(HarmonyOS)应用开发中,UI 组件的样式管理是构建高质量界面的核心。传统的 @Styles 和 @Extend 装饰器虽然能实现样式复用,但在跨文件复用、状态驱动刷新以及多态样式(如按压态、获焦态等)方面存在局限。AttributeModifier 是 ArkUI 提供的一种动态属性设置机制,它允许开发者通过自定义实现 AttributeModifier<T> 接口,将组件的样式与 UI 逻辑分离,从而实现更灵活、更高效的样式管理。
本教程将带你从零开始,全面掌握 AttributeModifier 的核心概念、使用方法、高级技巧及注意事项。
二、核心概念
AttributeModifier 的核心思想是将属性的设置逻辑封装成一个独立的类 ,然后通过 attributeModifier 方法将这个类绑定到组件上。当组件的状态发生变化时,AttributeModifier 会自动触发对应的回调方法,重新设置组件的属性。
2.1 接口定义
AttributeModifier<T> 是一个泛型接口,其中 T 代表目标组件的属性类型,例如 ButtonAttribute、TextAttribute 或通用的 CommonAttribute。
2.2 核心回调方法
applyNormalAttribute(instance: T): void:这是最核心的方法,用于设置组件的普通状态下的样式。当组件首次初始化或关联的状态变量发生变化时,此方法会被调用。- 多态样式回调 :除了普通状态,
AttributeModifier还支持为组件的不同交互状态设置样式,例如:applyPressedAttribute(instance: T): 按压态applyFocusedAttribute(instance: T): 获焦态applyDisabledAttribute(instance: T): 禁用态applySelectedAttribute(instance: T): 选中态
三、基础用法:封装共享样式
下面通过一个完整的示例,展示如何封装一个共享的按钮样式,并应用到多个按钮上。
3.1 定义 Modifier 类
首先,创建一个类并实现 AttributeModifier<ButtonAttribute> 接口。
typescript
// MyButtonModifier.ets
export class MyButtonModifier implements AttributeModifier<ButtonAttribute> {
// 普通状态样式
applyNormalAttribute(instance: ButtonAttribute): void {
instance.fontColor(Color.Black)
instance.fontSize(20)
instance.backgroundColor(Color.Orange)
instance.width(150)
instance.height(50)
}
// 按压状态样式
applyPressedAttribute(instance: ButtonAttribute): void {
instance.backgroundColor(Color.Red)
}
}
3.2 在页面中使用
在页面组件中,创建 MyButtonModifier 的实例,并通过 attributeModifier 方法将其绑定到按钮上。
typescript
// Index.ets
import { MyButtonModifier } from './MyButtonModifier';
@Entry
@Component
struct AttTestPage {
@State modifier: MyButtonModifier = new MyButtonModifier()
build() {
Column() {
Button("按钮1")
.attributeModifier(this.modifier)
Button("按钮2")
.attributeModifier(this.modifier)
Button("按钮3")
.attributeModifier(this.modifier)
}
.width('100%')
.height('100%')
.backgroundColor(Color.White)
.justifyContent(FlexAlign.Center)
}
}
运行效果:

说明:
- 通过
attributeModifier方法将MyButtonModifier实例绑定到组件。 - 当状态变量
modifier变化时,所有绑定的按钮会重新应用样式。 - 一个
Modifier实例可被多个组件共享,实现样式复用。
四、高级用法:多态样式与状态驱动
AttributeModifier 的真正威力在于其多态样式支持和状态驱动能力。
4.1 实现多态样式
通过实现 applyPressedAttribute 等回调,可以为组件的不同状态设置不同样式。
typescript
// AdvancedButtonModifier.ets
export class AdvancedButtonModifier implements AttributeModifier<ButtonAttribute> {
applyNormalAttribute(instance: ButtonAttribute): void {
instance.fontColor(Color.Black)
instance.fontSize(20)
instance.backgroundColor(Color.Orange)
instance.width(150)
instance.height(50)
}
applyPressedAttribute(instance: ButtonAttribute): void {
instance.backgroundColor(Color.Red) // 按压时变为红色
}
applyDisabledAttribute(instance: ButtonAttribute): void {
instance.fontColor(Color.White) // 禁用时文字变白色
}
}
typescript
// Index.ets
import { AdvancedButtonModifier } from './MyButtonModifier';
@Entry
@Component
struct AttTestPage {
@State modifier: AdvancedButtonModifier = new AdvancedButtonModifier()
build() {
Column({space: 20}) {
Button("按钮1")
.attributeModifier(this.modifier)
Button('按钮2')
.enabled(false)
.attributeModifier(this.modifier)
Button("按钮3")
.attributeModifier(this.modifier)
}
.width('100%')
.height('100%')
.backgroundColor(Color.White)
.justifyContent(FlexAlign.Center)
}
}
运行效果:

4.2 状态驱动刷新
AttributeModifier 可以响应状态变量的变化,实现动态样式更新。
typescript
@Entry
@Component
struct DynamicStylePage {
@State isPrimary: boolean = true
@State modifier: DynamicButtonModifier = new DynamicButtonModifier(this.isPrimary)
build() {
Column() {
Button(this.isPrimary ? "主要按钮" : "次要按钮")
.attributeModifier(this.modifier)
.onClick(() => {
this.isPrimary = !this.isPrimary
// 重新赋值 modifier 以触发 attributeModifier 重新应用
this.modifier = new DynamicButtonModifier(this.isPrimary)
})
}
.width('100%')
.height('100%')
.justifyContent(FlexAlign.Center)
}
}
class DynamicButtonModifier implements AttributeModifier<ButtonAttribute> {
private isPrimary: boolean = true
constructor(isPrimary: boolean = false) {
this.isPrimary = isPrimary;
}
applyNormalAttribute(instance: ButtonAttribute): void {
instance.width('80%')
instance.height(50)
instance.type(ButtonType.Capsule)
if (this.isPrimary) {
instance.backgroundColor(Color.Blue)
instance.fontColor(Color.White)
} else {
instance.backgroundColor(Color.Gray)
instance.fontColor(Color.Black)
}
}
}
上述代码中,DynamicStylePage 页面通过 @State isPrimary 控制按钮的主/次样式切换。每次点击按钮时,isPrimary 取反,并创建新的 DynamicButtonModifier 实例重新赋值给 modifier,从而触发 attributeModifier 重新调用 applyNormalAttribute,实现按钮样式的动态刷新。
运行效果:

五、注意事项与最佳实践
5.1 避免属性冲突
在 attributeModifier 中设置的属性,尽量不要与其他方法(如链式属性调用)设置的属性相同,否则在页面刷新时 attributeModifier 可能不生效。
5.2 未设置属性恢复默认值
当属性变化触发 applyXxxAttribute 时,本次未设置的属性会恢复为组件的默认值。因此,若需保留某些属性,需在回调中显式设置。
5.3 类型匹配
attributeModifier 的泛型参数 T 必须指定为组件对应的 Attribute 类型(如 ButtonAttribute、TextAttribute)或通用属性 CommonAttribute。
5.4 多次绑定顺序执行
一个组件可多次调用 attributeModifier 绑定不同的 Modifier 实例,每次状态刷新会按顺序执行这些实例的属性设置,遵循属性覆盖原则。
5.5 暂不支持属性/事件
部分属性或事件可能暂未支持通过 AttributeModifier 设置,若使用会抛出异常,需关注官方文档的更新。
六、总结
AttributeModifier 是鸿蒙应用开发中一种强大的样式管理机制,它通过将样式逻辑封装成独立的类,实现了样式与 UI 逻辑的分离,提高了代码的复用性和可维护性。
通过本文的学习,你应该已经掌握了 AttributeModifier 的核心概念、基础用法、高级技巧以及注意事项。在实际开发中,需要跨文件复用或实现多态样式的场景下,推荐使用 AttributeModifier 来管理组件的样式。