HarmonyOS鸿蒙NEXT中装饰器的使用
HarmonyOS鸿蒙NEXT中装饰器的使用
1、@State装饰器、@Prop装饰器、@Link装饰
@State装饰器:使得变量变为状态变量,影响UI(数据变化,UI变化)
@Prop装饰器装饰的变量和父组件建立单向的同步关系 (@Prop修饰的变量,api9不能初始化,api11能初始化)
父组件的@State数据变化,会同步到子组件@Prop,具体用法如下:
//父组件:Parent
[@State](/user/State) num:number = 0
build(){
Son({num:this.num})
}
//子组件:Son
[@Prop](/user/Prop) num:number
@Link装饰器装饰的变量与其父组件中的数据源共享相同的值
父组件的@State数据变化,会同步到子组件@Link数据
子组件@link数据变化,会同步到父组件@State数据具体用法如下:
//父组件:Parent
[@State](/user/State) num:number = 0
build(){
Son({num:$num})//api9必须使用$,api11开始也可以使用this了
}
//子组件:Son
[@Link](/user/Link) num:number
2、@Provide和@Consume装饰器
@Provide和@Consume可以通过相同的变量名或者相同的变量别名绑定
@Provide装饰器的变量是在祖先组件中,可以理解为被“提供”给后代的状态变量。@Consume装饰的变量是在后代组件中,去“消费”数据
特点:@Provide和@Consume可以通过相同的变量名或者相同的变量别名绑定
// 通过相同的变量名绑定
[@Provide](/user/Provide) a: number = 0; //祖先组件中定义
[@Consume](/user/Consume) a: number; //子孙组件中定义
// 通过相同的变量别名绑定
[@Provide](/user/Provide)('a') b: number = 0;//参数即为别名
[@Consume](/user/Consume)('a') c: number;
3、@ObjectLink、@Observed
@ObjectLink和@Observed类装饰器用于在涉及嵌套对象或数组的场景中进行双向数据同步:
被@Observed装饰的类,可以被观察到属性的变化;
子组件中@ObjectLink装饰器装饰的状态变量用于接收@Observed装饰的类的实例,和父组件中对应的状态变量建立双向数据绑定。这个实例可以是数组中的被@Observed装饰的项,或者是class object中的属性,这个属性同样也需要被@Observed装饰。
单独使用@Observed是没有任何作用的,需要搭配@ObjectLink或者@Prop使用。
限制条件:
- 使用@Observed装饰class会改变class原始的原型链,@Observed和其他类装饰器装饰同一个class可能会带来问题。
- @ObjectLink装饰器不能在@Entry装饰的自定义组件中使用。
- @ObjectLink装饰的变量类型需要为显式的被@Observed装饰的类,如果未指定类型,或其不是@Observed装饰的class,编译期会报错。
[@Observed](/user/Observed)
class Info {
count: number;
constructor(count: number) {
this.count = count;
}
}
class Test {
msg: number;
constructor(msg: number) {
this.msg = msg;
}
}
// 错误写法,编译报错
[@ObjectLink](/user/ObjectLink) count;
[@ObjectLink](/user/ObjectLink) test: Test;
// 正确写法
[@ObjectLink](/user/ObjectLink) count: Info;
4、@Watch
@Watch应用于对状态变量的监听。如果开发者需要关注某个状态变量的值是否改变,可以使用@Watch为状态变量设置回调函数。
@Watch用于监听状态变量的变化,当状态变量变化时,@Watch的回调方法将被调用
[@Component](/user/Component)
struct TotalView {
[@Prop](/user/Prop) [@Watch](/user/Watch)('onCountUpdated') count: number = 0;
[@State](/user/State) total: number = 0;
// 该函数是自定义组件的成员函数
// [@Watch](/user/Watch) 回调
// propName是被watch的属性名
// 多个状态绑定同一个[@Watch](/user/Watch)回调时,通过propName区分到底是哪个状态改变了
onCountUpdated(propName: string): void {
this.total += this.count;
}
build() {
Text(`Total: ${this.total}`)
}
}
[@Entry](/user/Entry)
[@Component](/user/Component)
struct CountModifier {
[@State](/user/State) count: number = 0;
build() {
Column() {
Button('add to basket')
.onClick(() => {
this.count++
})
TotalView({ count: this.count })
}
}
}
5、@Styles,@Extend,@Builder
@Styles装饰器:定义组件重用样式 (多个组件通用的样式)
@Styles装饰器,用于封装重复的通用样式代码。
如果多个不同类型的组件,有着相同的样式,例如宽高,背景色,字体大小。那么就可以将这下相同的样式代码抽取到一个@Styles装饰器修饰的方法中,供大家复用。
支持全局和局部定义:
// 全局
[@Styles](/user/Styles) functionName() { ... } //styles方法不能调用另一个styles方法***
// 在组件内
[@Component](/user/Component)
struct FancyUse {
[@Styles](/user/Styles) fancy() {
.height(100)
}
}
@Extend装饰器:定义扩展组件样式 (某一种组件自己的样式,私有属性)
@Extend,用于扩展原生组件样式。
如果同一类型的组件,有着很多相同的样式,例如按钮的类型,点击事件等。那么就可以将这些重复代码,抽过去到一个@Extend装饰器修饰的方法中,供此组件使用。
仅支持全局定义:(因为它相当于是给所有的此类组件使用)
// [@Extend](/user/Extend)(Text)可以支持Text的私有属性fontColor
[@Extend](/user/Extend)(Text) function fancy () {
.fontColor(Color.Red)
}
// superFancyText可以调用预定义的fancy
[@Extend](/user/Extend)(Text) function superFancyText(size:number) { //Extend方法可以调用另一个Extend方法
.fontSize(size)
.fancy()
}
@Builder装饰器:自定义构建函数
@Builder装饰器,用于封装重复的,复杂UI结构代码,例如List中的ListItem的布局结构,一般比较复杂就可以抽取到@Builder装饰的函数中
@Builder所装饰的函数遵循build()函数语法规则,开发者可以将重复使用的UI元素抽象成一个方法,在build方法里调用。
支持全局定义和局部定义:
//既然调用是通过this调用,那么说明是在组件内部定义
//组件内部定义不需要关键字function
[@Builder](/user/Builder) MyBuilderFunction() { ... }
//全局定义
MyGlobalBuilderFunction()
@BuilderParam装饰器:引用@Builder函数
当开发者创建了自定义组件,并想对该组件添加特定功能时,例如在自定义组件中添加一个点击跳转操作。若直接在组件内嵌入事件方法,将会导致所有引入该自定义组件的地方均增加了该功能。
为解决此问题,ArkUI引入了@BuilderParam装饰器,该装饰器用于声明任意UI描述的一个元素,类似slot占位符。
使得自定义组件更加灵活
代码:
[@Component](/user/Component)
struct Child {
[@Builder](/user/Builder) customBuilder() {}
// 使用父组件[@Builder](/user/Builder)装饰的方法初始化子组件[@BuilderParam](/user/BuilderParam)
[@BuilderParam](/user/BuilderParam) customBuilderParam: () => void = this.customBuilder;
build() {
Column() {
this.customBuilderParam()
}
}
}
[@Entry](/user/Entry)
[@Component](/user/Component)
struct Parent {
[@Builder](/user/Builder) componentBuilder() {
Text(`Parent builder `)
}
build() {
Column() {
Child({ customBuilderParam: this.componentBuilder })
}
}
}更多关于HarmonyOS鸿蒙NEXT中装饰器的使用的实战教程也可以访问 https://www.itying.com/category-93-b0.html
在HarmonyOS鸿蒙NEXT中,装饰器是一种用于增强或修改类、方法、属性等行为的语法特性。装饰器通过@符号来标识,可以应用于类、方法、属性或参数上。鸿蒙NEXT中的装饰器主要用于实现一些通用的功能,如日志记录、权限检查、数据绑定等。
装饰器的使用场景包括:
- 类装饰器:用于修改类的行为,如添加元数据、扩展类的功能等。
- 方法装饰器:用于在方法执行前后添加额外的逻辑,如日志记录、权限验证等。
- 属性装饰器:用于对类属性进行拦截或修改,如数据绑定、属性校验等。
- 参数装饰器:用于对方法的参数进行拦截或修改,如参数校验、参数注入等。
鸿蒙NEXT中的装饰器通过@符号来标识,例如:
@log
class MyClass {
@readonly
myProperty: string;
@validate
myMethod(@inject param: string) {
// 方法逻辑
}
}
在这个例子中,@log是类装饰器,@readonly是属性装饰器,@validate是方法装饰器,@inject是参数装饰器。
装饰器的实现通常是一个函数,该函数接收目标对象、属性名或参数索引等信息,并返回一个修改后的对象或执行某些逻辑。鸿蒙NEXT中的装饰器语法与TypeScript中的装饰器类似,但具体实现可能有所不同,以适应鸿蒙系统的特性和需求。
总结:鸿蒙NEXT中的装饰器是一种强大的语法特性,用于增强或修改类、方法、属性等的行为,适用于日志记录、权限检查、数据绑定等场景。
更多关于HarmonyOS鸿蒙NEXT中装饰器的使用的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
在HarmonyOS鸿蒙NEXT中,装饰器是一种用于修改类、方法或属性的特殊语法。通过在类、方法或属性前添加@符号和装饰器函数,开发者可以扩展或修改其行为。常见场景包括日志记录、权限校验、数据绑定等。例如:
function log(target, name, descriptor) {
const original = descriptor.value;
descriptor.value = function(...args) {
console.log(`Calling ${name} with`, args);
return original.apply(this, args);
};
return descriptor;
}
class MyClass {
@log
myMethod() {
// 方法逻辑
}
}
上述代码通过@log装饰器在myMethod执行前后添加日志记录功能。鸿蒙NEXT的装饰器机制与标准JavaScript/TypeScript一致,便于开发者快速上手。

