一、概述
声明式语法引入了@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@Componentstruct 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、动态状态切换
@Componentstruct 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 = falsesetVIPStatus(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体系。
关注我获取更多知识或者投稿