1. HarmonyOS @Style 、 @Extend、自定义扩展(AttributeModifier、AttributeUpdater)
@Styles装饰器:定义组件重用样式
;@Extend装饰器:定义扩展组件样式
自定义扩展:AttributeModifier、AttributeUpdater
1.1. 区别
1.1.1. 对比
声明式语法引入了@Styles和@Extend两个装饰器,可以解决部分复用的问题,但是存在以下受限场景:
(1)@Styles和@Extend均是编译期处理,不支持跨文件的导出复用。
(2)@Styles仅能支持通用属性、事件,不支持组件特有的属性。
(3)@Styles虽然支持在多态样式下使用,但不支持传参,无法对外开放一些属性。
(4)@Extend虽然能支持特定组件的私有属性、事件,但同样不支持跨文件导出复用。
(5)@Styles、@Extend对于属性设置,无法支持业务逻辑编写,动态决定是否设置某些属性。只能通过三元表达式对所有可能设置的属性进行全量设置,设置大量属性时效率低下。
(为了解决上述问题,ArkUI引入了AttributeModifier的机制,可以通过Modifier对象动态修改属性。能力对比如下:
项目 | @Styles | @Extend | AttributeModifier |
---|---|---|---|
跨文件导出 | 不支持 | 不支持 | 支持 |
通用属性设置 | 支持 | 支持 | 支持 |
通用事件设置 | 支持 | 支持 | 部分支持 |
组件特有属性设置 | 不支持 | 支持 | 部分支持 |
组件特有事件设置 | 不支持 | 支持 | 部分支持 |
参数传递 | 不支持 | 支持 | 支持 |
多态样式 | 支持 | 不支持 | 支持 |
业务逻辑 | 不支持 | 不支持 | 支持 |
可以看出,AttributeModifier的能力和灵活性更好,当前持续在构建全量的属性、事件设置能力。未来,AttributeModifier可以替代@Styles和@Extend几乎所有的能力,建议上述场景都使用AttributeModifier。
1.1.2. @Style 和 @Extend 是否支持export导出
方舟UI框架(ArkUI)解答文档
(1)@Styles或@Extend目前不支持export导出,后续这两个装饰器不会继续演进。
(2)推荐开发者使用新的样式复用方法,通过attributeModifier属性动态的设置组件,通过自定义class继承对应基础组件的Modifier,在class中设置复用的属性,对应class也没有无法export的限制。但是attributeModifier的复用能力仍有缺陷,目前不支持事件手势,这两个能力已有需求跟踪。
1.2. @Styles装饰器:定义组件重用样式
如果每个组件的样式都需要单独设置,在开发过程中会出现大量代码在进行重复样式设置,虽然可以复制粘贴,但为了代码简洁性和后续方便维护,我们推出了可以提炼公共样式进行复用的装饰器@Styles。
@Styles装饰器可以将多条样式设置提炼成一个方法,直接在组件声明的位置调用。通过@Styles装饰器可以快速定义并复用自定义样式。
说明:
从API version 9开始,该装饰器支持在ArkTS卡片中使用。
从API version 11开始,该装饰器支持在元服务中使用。
1.2.1. 装饰器使用说明
(1)当前@Styles仅支持通用属性和通用事件。
@Styles方法不支持参数,反例如下。
// 反例: @Styles不支持参数
@Styles function globalFancy (value: number) {
.width(value)
}
(2)@Styles可以定义在组件内或全局,在全局定义时需在方法名前面添加function关键字,组件内定义时则不需要添加function关键字。
说明
只能在当前文件内使用,不支持export。
如果想实现export功能,推荐使用AttributeModifier
// 全局
@Styles function functionName() { ... }
// 在组件内
@Component
struct FancyUse {
@Styles fancy() {
.height(100)
}
}
(3)如果要实现跨文件操作的功能,可以参考使用动态属性设置。
// index.ets
import { MyButtonModifier } from './setAttribute'
@Entry
@Component
struct attributeDemo {
@State modifier: MyButtonModifier = new MyButtonModifier()
build() {
Row() {
Column() {
Button("Button")
.attributeModifier(this.modifier)
.onClick(() => {
this.modifier.isDark = !this.modifier.isDark
})
}
.width('100%')
}
.height('100%')
}
}
// setAttribute.ets
export class MyButtonModifier implements AttributeModifier<ButtonAttribute> {
isDark: boolean = false
applyNormalAttribute(instance: ButtonAttribute): void {
if (this.isDark) {
instance.backgroundColor(Color.Black)
} else {
instance.backgroundColor(Color.Red)
}
}
}
(4)定义在组件内的@Styles可以通过this访问组件的常量和状态变量,并可以在@Styles里通过事件来改变状态变量的值,示例如下:
@Component
struct FancyUse {
@State heightValue: number = 100
@Styles fancy() {
.height(this.heightValue)
.backgroundColor(Color.Yellow)
.onClick(() => {
this.heightValue = 200
})
}
}
(5)组件内@Styles的优先级高于全局@Styles。
框架优先找当前组件内的@Styles,如果找不到,则会全局查找。
1.2.2. 使用场景
以下示例中演示了组件内@Styles和全局@Styles的用法。
import { TitleBar } from '../../components/common/TitleBar'
import { router } from '@kit.ArkUI'
import { RouterParams } from 'zzslib'
/**
* @Styles可以定义在组件内、外
*/
/**
* 组件外
* 在组件外定义时需带上function关键字
*/
@Styles
function styleGlobal() {
.backgroundColor(Color.Red)
.width(100)
.height(100)
}
@Styles
function styleGlobal2() {
// .backgroundColor(color)
.width(100)
.height(100)
}
@Entry
@Component
struct StylePage {
@State pageTitle: string = "网格列表"
aboutToAppear() {
try {
this.pageTitle = (router
.getParams() as RouterParams).title
} catch (e) {
}
}
/**
* 组件内
* 在组件外定义时不需要带function关键字
*/
@Styles
styleFancy() {
.backgroundColor(Color.Blue)
.width(100)
.height(100)
}
build() {
Column() {
TitleBar({ pageTitle: $pageTitle })
Text("组件外样式")
.styleGlobal()
.fontSize(30)
Text("组件内样式")
.styleFancy()
.fontSize(30)
//@Styles还可以在StateStyles属性内部使用,
// 在组件处于不同的状态时赋予相应的属性。
//在StateStyles内可以直接调用组件外定义的Styles,
// 但需要通过this关键字调用组件内定义的Styles。
Button() {
Text("StateStyles")
}
.stateStyles({
normal: {
.width(180)
.height(180)
},
disabled: this.styleFancy,
pressed: styleGlobal
})
}
}
}
1.3. @Extend 扩展原生组件样式
@Extend,用于扩展原生组件样式
说明:
从API version 9开始,该装饰器支持在ArkTS卡片中使用。
从API version 11开始,该装饰器支持在元服务中使用。
1.3.1. 装饰器使用说明
1.3.1.1. 语法
@Extend(UIComponentName) function functionName { ... }
1.3.1.2. 使用规则
(1)和@Styles不同,@Extend仅支持在全局定义,不支持在组件内部定义。
说明
只能在当前文件内使用,不支持export
如果想实现export功能,推荐使用AttributeModifier
(2)和@Styles不同,@Extend支持封装指定组件的私有属性、私有事件和自身定义的全局方法。
// @Extend(Text)可以支持Text的私有属性fontColor
@Extend(Text) function fancy () {
.fontColor(Color.Red)
}
// superFancyText可以调用预定义的fancy
@Extend(Text) function superFancyText(size:number) {
.fontSize(size)
.fancy()
}
(3)和@Styles不同,@Extend装饰的方法支持参数,开发者可以在调用时传递参数,调用遵循TS方法传值调用。
// xxx.ets
@Extend(Text) function fancy (fontSize: number) {
.fontColor(Color.Red)
.fontSize(fontSize)
}
@Entry
@Component
struct FancyUse {
build() {
Row({ space: 10 }) {
Text('Fancy')
.fancy(16)
Text('Fancy')
.fancy(24)
}
}
}
(4)@Extend装饰的方法的参数可以为function,作为Event事件的句柄。
@Extend(Text) function makeMeClick(onClick: () => void) {
.backgroundColor(Color.Blue)
.onClick(onClick)
}
@Entry
@Component
struct FancyUse {
@State label: string = 'Hello World';
onClickHandler() {
this.label = 'Hello ArkUI';
}
build() {
Row({ space: 10 }) {
Text(`${this.label}`)
.makeMeClick(() => {this.onClickHandler()})
}
}
}
(5)@Extend的参数可以为状态变量,当状态变量改变时,UI可以正常的被刷新渲染。
@Extend(Text) function fancy (fontSize: number) {
.fontColor(Color.Red)
.fontSize(fontSize)
}
@Entry
@Component
struct FancyUse {
@State fontSizeValue: number = 20
build() {
Row({ space: 10 }) {
Text('Fancy')
.fancy(this.fontSizeValue)
.onClick(() => {
this.fontSizeValue = 30
})
}
}
}
1.3.2. 使用场景
通过@Extend组合样式后,使得代码更加简洁,增强可读性。
import { router } from '@kit.ArkUI'
import { RouterParams } from 'zzslib'
import { TitleBar } from '../../components/common/TitleBar'
@Extend(Text)
function extendText() {
.fontSize(15)
.maxLines(1)
.textOverflow({ overflow: TextOverflow.Ellipsis })
.margin({
top: 20,
right: 20,
bottom: 20,
left: 20
})
.padding(20)
.border({
width: {
left: 1,
right: 1,
top: 1,
bottom: 1
},
color: {
left: Color.Blue,
right: Color.Blue,
top: Color.Red,
bottom: $r('app.color.primary_font_content')
},
radius: {
topLeft: 0,
topRight: 0,
bottomLeft: 0,
bottomRight: 0
},
style: {
left: BorderStyle.Dotted,
right: BorderStyle.Dotted,
top: BorderStyle.Solid,
bottom: BorderStyle.Solid
}
})
}
// @Extend(Text)可以支持Text的私有属性fontColor
@Extend(Text)
function fancy() {
.fontColor(Color.Red)
}
// superFancyText可以调用预定义的fancy
@Extend(Text)
function superFancyText(size: number) {
.fontSize(size)
.fancy()
}
@Extend(Text)
function extendTextLine(fontSize: number) {
.fontSize(fontSize)
.fontColor($r('app.color.primary_font_title'))
.maxLines(1)
.margin({ top: 20 })
}
@Entry
@Component
struct ExtendPage {
@State pageTitle: string = "Extend"
aboutToAppear() {
try {
this.pageTitle = (router
.getParams() as RouterParams).title
} catch (e) {
}
}
build() {
Column() {
TitleBar({ pageTitle: $pageTitle })
Text('全局样式')
.extendText()
Text('私有事件和自身定义的全局方法')
.superFancyText(20)
Text('@Extend装饰传递参数')
.extendTextLine(20)
}
}
}
1.4. AttributeModifier
声明式语法引入了@Styles和@Extend两个装饰器,可以解决部分复用的问题,但是存在以下受限场景,为此,ArkUI引入了AttributeModifier的机制,可以通过Modifier对象动态修改属性。AttributeModifier的能力和灵活性更好,当前持续在构建全量的属性、事件设置能力。未来,AttributeModifier可以替代@Styles和@Extend几乎所有的能力,建议上述场景都使用AttributeModifier。
1.4.1.接口定义
declare interface AttributeModifier<T> {
applyNormalAttribute?(instance: T): void;
applyPressedAttribute?(instance: T): void;
applyFocusedAttribute?(instance: T): void;
applyDisabledAttribute?(instance: T): void;
applySelectedAttribute?(instance: T): void;
}
AttributeModifier是一个接口,需要开发者实现ApplyXxxAttribute的方法。Xxx表示多态的场景,支持默认态、按压态、焦点态、禁用态、选择态。其中,T是组件的属性类型,开发者可以在回调中获取到属性对象,通过该对象设置属性。
declare class CommonMethod<T> {
attributeModifier(modifier: AttributeModifier<T>): T;
}
}
在组件的通用方法上,增加了attributeModifier传入自定义的Modifier。由于组件在实例化时会明确T的类型,所以调用该方法时,T必须是组件对应的Attribute类型,或者是CommonAttribute。
1.4.2. 行为规格
(1)组件通用方法attributeModifier支持传入一个实现AttributeModifier接口的实例,T必须是组件对应的Attribute类型,或者是CommonAttribute。
(2)在组件首次初始化或者关联的状态变量发生变化时,如果传入的实例实现了对应接口,会触发applyNormalAttribute。
(3)回调applyNormalAttribute时,会传入组件属性对象,通过该对象可以设置当前组件的属性/事件。
暂未支持的属性/事件,执行时会抛异常。
(4)属性变化触发ApplyXxxAttribute函数时,该组件之前已设置的属性,在本次变化后未设置的属性会恢复为属性的默认值。
(5)可以通过该接口使用多态样式的功能,例如如果需要在组件进入按压态时设置某些属性,就可以通过自定义实现applyPressedAttribute方法完成。
(6)一个组件上同时使用属性方法和applyNormalAttribute设置相同的属性,遵循属性覆盖原则,即后设置的属性生效。
(7)一个Modifier实例对象可以在多个组件上使用。
(8)一个组件上多次使用applyNormalAttribute设置不同的Modifier实例,每次状态变量刷新均会按顺序执行这些实例的方法属性设置,同样遵循属性覆盖原则。
1.4.3. 属性设置与修改
AttributeModifier可以分离UI与样式,支持参数传递及业务逻辑编写,并且通过状态变量触发刷新。
// button_modifier.ets
export class MyButtonModifier implements AttributeModifier<ButtonAttribute> {
// 可以实现一个Modifier,定义私有的成员变量,外部可动态修改
isDark: boolean = false
// 通过构造函数,创建时传参
constructor(dark?: boolean) {
this.isDark = dark ? dark : false
}
applyNormalAttribute(instance: ButtonAttribute): void {
// instance为Button的属性对象,可以通过instance对象对属性进行修改
if (this.isDark) { // 支持业务逻辑的编写
// 属性变化触发apply函数时,变化前已设置并且变化后未设置的属性会恢复为默认值
instance.backgroundColor(Color.Black)
} else {
// 支持属性的链式调用
instance.backgroundColor(Color.Red)
.borderColor(Color.Black)
.borderWidth(2)
}
}
}
// demo.ets
import { MyButtonModifier } from './button_modifier'
@Entry
@Component
struct attributeDemo {
// 支持用状态装饰器修饰,行为和普通的对象一致
@State modifier: MyButtonModifier = new MyButtonModifier(true);
build() {
Row() {
Column() {
Button("Button")
.attributeModifier(this.modifier)
.onClick(() => {
// 对象的一层属性被修改时,会触发UI刷新,重新执行applyNormalAttribute
this.modifier.isDark = !this.modifier.isDark
})
}
.width('100%')
}
.height('100%')
}
}
一个组件上同时使用属性方法和applyNormalAttribute设置相同的属性,遵循属性覆盖原则,即后设置的属性生效。
// button_modifier.ets
export class MyButtonModifier implements AttributeModifier<ButtonAttribute> {
isDark: boolean = false
constructor(dark?: boolean) {
this.isDark = dark ? dark : false
}
applyNormalAttribute(instance: ButtonAttribute): void {
if (this.isDark) {
instance.backgroundColor(Color.Black)
} else {
instance.backgroundColor(Color.Red)
.borderColor(Color.Black)
.borderWidth(2)
}
}
}
// demo.ets
import { MyButtonModifier } from './button_modifier';
@Entry
@Component
struct attributeDemo {
@State modifier: MyButtonModifier = new MyButtonModifier(true);
build() {
Row() {
Column() {
// 先设置属性,后设置modifier,按钮颜色会跟随modifier的值改变
Button("Button")
.backgroundColor(Color.Blue)
.attributeModifier(this.modifier)
.onClick(() => {
this.modifier.isDark = !this.modifier.isDark
})
}
.width('100%')
}
.height('100%')
}
}
一个组件上多次使用applyNormalAttribute设置不同的Modifier实例,每次状态变量刷新均会按顺序执行这些实例的方法属性设置,遵循属性覆盖原则,即后设置的属性生效。
// button_modifier.ets
export class MyButtonModifier implements AttributeModifier<ButtonAttribute> {
isDark: boolean = false
constructor(dark?: boolean) {
this.isDark = dark ? dark : false
}
applyNormalAttribute(instance: ButtonAttribute): void {
if (this.isDark) {
instance.backgroundColor(Color.Black)
.width(200)
} else {
instance.backgroundColor(Color.Red)
.width(100)
}
}
}
// button_modifier2.ets
export class MyButtonModifier2 implements AttributeModifier<ButtonAttribute> {
isDark2: boolean = false
constructor(dark?: boolean) {
this.isDark2 = dark ? dark : false
}
applyNormalAttribute(instance: ButtonAttribute): void {
if (this.isDark2) {
instance.backgroundColor('#2787D9')
} else {
instance.backgroundColor('#707070')
}
}
}
// demo.ets
import { MyButtonModifier } from './button_modifier';
import { MyButtonModifier2 } from './button_modifier2';
@Entry
@Component
struct attributeDemo {
@State modifier: MyButtonModifier = new MyButtonModifier(true);
@State modifier2: MyButtonModifier2 = new MyButtonModifier2(true);
build() {
Row() {
Column() {
Button("Button")
.attributeModifier(this.modifier)
.attributeModifier(this.modifier2)
.onClick(() => {
this.modifier.isDark = !this.modifier.isDark
this.modifier2.isDark2 = !this.modifier2.isDark2
})
}
.width('100%')
}
.height('100%')
}
}
1.4.4. 设置多态样式、事件
使用AttributeModifier设置多态样式、事件,实现事件逻辑的复用,支持默认态、按压态、焦点态、禁用态、选择态。例如如果需要在组件进入按压态时设置某些属性,就可以通过自定义实现applyPressedAttribute方法完成。
// button_modifier.ets
export class MyButtonModifier implements AttributeModifier<ButtonAttribute> {
applyNormalAttribute(instance: ButtonAttribute): void {
// instance为Button的属性对象,设置正常状态下属性值
instance.backgroundColor(Color.Red)
.borderColor(Color.Black)
.borderWidth(2)
}
applyPressedAttribute(instance: ButtonAttribute): void {
// instance为Button的属性对象,设置按压状态下属性值
instance.backgroundColor(Color.Green)
.borderColor(Color.Orange)
.borderWidth(5)
}
}
// demo.ets
import { MyButtonModifier } from './button_modifier'
@Entry
@Component
struct attributeDemo {
@State modifier: MyButtonModifier = new MyButtonModifier();
build() {
Row() {
Column() {
Button("Button")
.attributeModifier(this.modifier)
}
.width('100%')
}
.height('100%')
}
}
1.4.5. 示例
import { CommonModifier, router } from '@kit.ArkUI'
import { RouterParams } from 'zzslib'
import { TitleBar } from '../../components/common/TitleBar'
class MyButtonModifier implements AttributeModifier<ButtonAttribute> {
isDark: boolean = false
// applyNormalAttribute(instance: ButtonAttribute): void {
// if (this.isDark) {
// instance.backgroundColor(Color.Black)
// } else {
// instance.backgroundColor(Color.Red)
// }
// }
/**
* 组件普通状态时的样式
* @param instance
*/
applyNormalAttribute(instance: ButtonAttribute): void {
instance.backgroundColor(Color.Black)
}
/**
* 组件按压状态的样式
* @param instance
*/
applyPressedAttribute(instance: ButtonAttribute): void {
instance.backgroundColor(Color.Red)
}
/**
* 组件禁用状态的样式
* @param instance
*/
applyDisabledAttribute(instance: ButtonAttribute): void {
}
/**
* 组件选中状态的样式
* @param instance
*/
applySelectedAttribute(instance: ButtonAttribute): void {
}
}
class MyModifier extends CommonModifier {
applyNormalAttribute(instance: CommonAttribute): void {
super.applyNormalAttribute?.(instance);
}
public setGroup1(): void {
this.borderStyle(BorderStyle.Dotted)
this.borderWidth(8)
}
public setGroup2(): void {
this.borderStyle(BorderStyle.Dashed)
this.borderWidth(8)
}
}
@Component
struct MyImage1 {
@Link modifier: CommonModifier
build() {
Image($r("app.media.icon_main_apply_normal"))
.attributeModifier(this.modifier as MyModifier)
}
}
/**
* 设置自定义Modifier给一个组件,该组件对应属性生效。
* 自定义Modifier属性值变化,组件对应属性也会变化。自定义Modifier类型为基类,
* 构造的对象为子类对象,使用时要通过as进行类型断言为子类。
* 一个自定义Modifier设置给两个组件,Modifier属性变化的时候对两个组件同时生效。
* 一个Modifier设置了属性A和属性B,再设置属性C和属性D,4个属性同时在组件上生效。
* 自定义Modifier不支持@State标注的状态数据的变化感知,见示例2。
* 多次通过attributeModifier设置属性时,生效的属性为所有属性的并集,相同属性按照设置顺序生效。
*/
@Entry
@Component
struct AttributeModifierPage {
@State pageTitle: string = "自定义样式"
@State modifier: MyButtonModifier = new MyButtonModifier()
@State myModifier: CommonModifier = new MyModifier()
.width(100).height(100).margin(10)
index: number = 0;
aboutToAppear() {
try {
this.pageTitle = (router.getParams() as RouterParams).title
} catch (e) {
}
}
build() {
Column() {
TitleBar({ pageTitle: $pageTitle })
Column() {
// Button("Button")
// .attributeModifier(this.modifier)
// .onClick(() => {
// this.modifier.isDark = !this.modifier.isDark
// })
Button("Button")
.attributeModifier(this.modifier)
Button($r("app.string.EntryAbility_label"))
.margin(10)
.onClick(() => {
console.log("Modifier", "onClick")
this.index++;
if (this.index % 2 === 1) {
(this.myModifier as MyModifier).setGroup1()
console.log("Modifier", "setGroup1")
} else {
(this.myModifier as MyModifier).setGroup2()
console.log("Modifier", "setGroup2")
}
})
MyImage1({ modifier: this.myModifier })
}
.width('100%')
}
.height('100%')
}
}
1.5. AttributeUpdater
1.5.1. 概述
大量属性频繁更新时,如果使用状态变量,会导致前端状态管理计算量太大,并需要对单个组件进行全量的属性更新。虽然可以通过AttributeModifier的机制按需更新,但是前端还是默认会有一些diff和reset的策略。
为此引入了AttributeUpdater的能力,它是一个特殊的AttributeModifier,除了继承AttributeModifier的能力,还提供了获取属性对象的能力。通过属性对象可以不经过状态变量,直接更新对应属性。使用AttributeUpdater,开发者可实现自定义的更新策略,进一步提高属性更新的性能。但是由于该能力比较灵活,无法限制“单一数据源”的规则,同时和状态变量更新相同属性时,存在相互覆盖的情况,需要开发者自己保障属性设置的合理性。
1.5.2. 接口定义
export declare class AttributeUpdater<T, C = Initializer<T>> implements AttributeModifier<T> {
applyNormalAttribute?(instance: T): void;
initializeModifier(instance: T): void;
get attribute(): T | undefined;
updateConstructorParams: C;
}
AttributeUpdater实现了AttributeModifier接口,额外提供了initializeModifier,可以对组件的属性进行初始化,并且通过attribute属性方法,获取到属性对象,通过该对象直接更新对应组件的属性。另外也可以直接通过updateConstructorParams更新组件的构造参数。
1.5.3. 行为规格
(1)开发者可以实现一个AttributeUpdater的类,并通过组件的AttributeModifier设置,首次绑定时会触发initializeModifier方法,进行属性的初始化,后续其它的生命周期和AttributeModifier保持一致。
(2)组件初始化完成之后,可以通过AttributeUpdater实例的attribute属性方法,获取到属性对象,否则为undefined。
(3)通过attribute属性对象直接修改属性,会将最新设置的属性记录在当前对象中,并立即触发组件属性的更新。
(4)如果将AttributeUpdater实例标记为状态变量进行修改,或者通过其它状态变量更新对应组件的属性,会触发applyNormalAttribute的流程,如果开发者没有覆写该逻辑,默认会将属性对象记录的所有属性,批量进行一次更新。
(5)如果开发者复写applyNormalAttribute的逻辑,并且不调用super的该方法,将会失去获取attribute属性对象的能力,不会调用initializeModifier方法。
(6)一个AttributeUpdater对象只能同时关联一个组件,否则只会有一个组件生效属性设置。
1.5.4. 通过modifier直接修改属性
组件初始化完成之后,可以通过AttributeUpdater实例的attribute属性方法,获取到属性对象,通过属性对象直接修改属性,会立即触发组件属性的更新。
import { AttributeUpdater } from '@ohos.arkui.modifier'
class MyButtonModifier extends AttributeUpdater<ButtonAttribute> {
initializeModifier(instance: ButtonAttribute): void {
instance.backgroundColor('#2787D9')
.width('50%')
.height(30)
}
}
@Entry
@Component
struct updaterDemo {
modifier: MyButtonModifier = new MyButtonModifier()
build() {
Row() {
Column() {
Button("Button")
.attributeModifier(this.modifier)
.onClick(() => {
this.modifier.attribute?.backgroundColor('#17A98D').width('30%')
})
}
.width('100%')
}
.height('100%')
}
}
1.5.4. 通过modifier更新组件的构造参数
可以直接通过AttributeUpdater实例的updateConstructorParams方法,更新组件的构造参数。
import { AttributeUpdater } from '@ohos.arkui.modifier'
class MyTextModifier extends AttributeUpdater<TextAttribute, TextInterface> {
initializeModifier(instance: TextAttribute): void {
}
}
@Entry
@Component
struct updaterDemo {
modifier: MyTextModifier = new MyTextModifier()
build() {
Row() {
Column() {
Text("Text")
.attributeModifier(this.modifier)
.fontColor(Color.White)
.fontSize(14)
.border({ width: 1 })
.textAlign(TextAlign.Center)
.lineHeight(20)
.width(200)
.height(50)
.backgroundColor('#2787D9')
.onClick(() => {
this.modifier.updateConstructorParams('Update');
})
}
.width('100%')
}
.height('100%')
}
}