一、概述
声明式语法引入了@Styles和@Extend两个装饰器,可以解决复用相同自定义样式的问题,但是存在以下受限场景:
@Styles和@Extend均是编译期处理,不支持跨文件的导出复用。
@Styles仅能支持通用属性、事件,不支持组件特有的属性。
@Styles虽然支持在多态样式下使用,但不支持传参,无法对外开放一些属性。
@Extend虽然能支持特定组件的私有属性、事件,但同样不支持跨文件导出复用。
@Styles、@Extend对于属性设置,无法支持业务逻辑编写,动态决定是否设置某些属性,只能通过三元表达式对所有可能设置的属性进行全量设置,设置大量属性时效率较低。
为了解决上述问题,ArkUI引入了AttributeModifier机制,可以通过Modifier对象动态修改属性。能力对比如下:
能力 |
@Styles |
@Extend |
AttributeModifier |
---|---|---|---|
跨文件导出 |
不支持 |
不支持 |
支持 |
通用属性设置 |
支持 |
支持 |
支持 |
通用事件设置 |
支持 |
支持 |
部分支持 |
组件特有属性设置 |
不支持 |
支持 |
部分支持 |
组件特有事件设置 |
不支持 |
支持 |
部分支持 |
参数传递 |
不支持 |
支持 |
支持 |
多态样式 |
支持 |
不支持 |
支持 |
业务逻辑 |
不支持 |
不支持 |
支持 |
可以看出,与@Styles和@Extend相比,AttributeModifier提供了更强的能力和灵活性,且在持续完善全量的属性和事件设置能力,因此推荐优先使用AttributeModifier。
二、接口定义
declare interface AttributeModifier<T> {//定义组件正常状态的属性值 applyNormalAttribute?(instance: T): void;//定义组件按下的属性,比如点击事件 applyPressedAttribute?(instance: T): void;//定义焦点相关的属性 applyFocusedAttribute?(instance: T): void;//定义组件禁用属性 applyDisabledAttribute?(instance: T): void;//定义选择属性 applySelectedAttribute?(instance: T): void;}
三、基础使用范式
1、跨文件样式复用
// TextModifier.ets(独立文件) export class TextModifier implements AttributeModifier<TextAttribute> { applyNormalAttribute(instance: TextAttribute): void { instance.width('100%') .fontSize(16) .fontColor(Color.Black) .margin({ top: 10 }) } }
创建实现AttributeModifier<T>
接口的样式类,支持全局导出复用,解决@Styles无法跨文件的问题
2、组件绑定样式
// 宿主组件
import { TextModifier } from './TextModifier'
@Entry
@Component
struct MyPage {
@State textModifier: TextModifier = new TextModifier()
build() {
Column() {
Text("鸿蒙Next核心特性")
.attributeModifier(this.textModifier)
}
}
}
通过.attributeModifier()
方法动态注入样式,支持状态感知35
四、多状态控制
1、五态样式覆盖
export class ButtonModifier implements AttributeModifier<ButtonAttribute> {
// 默认态
applyNormalAttribute(instance: ButtonAttribute): void {
instance.backgroundColor(Color.Blue)
} // 按压态
applyPressedAttribute(instance: ButtonAttribute): void {
instance.backgroundColor(Color.Green)
} // 禁用态
applyDisabledAttribute(instance: ButtonAttribute): void {
instance.backgroundColor(Color.Gray)
}
}
实现不同交互状态的样式回调方法46
2、动态状态切换
@Component
struct DynamicButton {
@State isActive: boolean = false
@State modifier: ButtonModifier = new ButtonModifier()
build() {
Button('状态按钮')
.attributeModifier(this.modifier)
.onClick(() => {
this.isActive = !this.isActive
// 动态修改modifier属性
this.modifier.applyNormalAttribute = (instance) => {
instance.backgroundColor(this.isActive ? Color.Red : Color.Blue)
}
})
}
}
结合@State变量实现运行时样式更新36
五、高级场景应用
1、业务逻辑集成
export class AuthButtonModifier implements AttributeModifier<ButtonAttribute> { private isVIP: boolean = false setVIPStatus(status: boolean) { this.isVIP = status } applyNormalAttribute(instance: ButtonAttribute): void { instance.backgroundColor(this.isVIP ? Color.Gold : Color.Gray) .fontColor(this.isVIP ? Color.Black : Color.White) } }
在样式中嵌入条件判断,实现动态属性设置57
2、组件库开发
// 企业规范库 export class PrimaryButtonModifier implements AttributeModifier<ButtonAttribute> { applyNormalAttribute(instance: ButtonAttribute): void { instance.width(240) .height(48) .borderRadius(24) .fontSize(16) .backgroundColor('#007AFF') } }
封装企业级UI规范,统一管理按钮/输入框等组件样式18
六、典型使用场景
场景类型 |
技术方案 |
优势体现 |
---|---|---|
多主题切换 |
创建不同主题的Modifier类,运行时动态切换57 |
样式与逻辑解耦 |
A/B测试 |
通过工厂模式生成不同样式的Modifier实例36 |
动态部署无感知 |
无障碍适配 |
在Modifier中集成大字模式/高对比度样式48 |
状态感知自动化 |
组件库维护 |
将Modifier独立为har包,跨项目复用18 |
统一设计规范 |
注意事项
1、类型安全
明确指定泛型类型
AttributeModifier<T>
中的T
(如ButtonAttribute
),避免属性设置错误68
2、性能优化
避免在apply方法内进行耗时操作,复杂逻辑应前置处理35
3、兼容性
需鸿蒙API Version 11+支持,低版本需降级方案12
代码验证示例
// 验证多态样式
let modifier = new ButtonModifier()
Button('智能按钮')
.attributeModifier(modifier)
.onTouch((event) => {
if (event.type === TouchType.Down) {
modifier.applyPressedAttribute(modifier)
} else if (event.type === TouchType.Up) {
modifier.applyNormalAttribute(modifier)
}
})
通过以上方案,开发者可构建高复用性、强可维护的鸿蒙Next UI体系。
关注我获取更多知识或者投稿