本文正在参加华为鸿蒙有奖征文征文活动
我总结了全部关于鸿蒙的装饰器,简单地一一介绍一下:
@Entry、@Component、@State、@Prop、@Link、@Builder、@Style、@Extends、@BuilderParam、@Observe、@objectLink、@Provide、@Consume、@Watch;
其它:@CustomDialog、@Preview、@Reusable、@Concurrent、@Track;
-
@Component表示自定义组件;
-
@Entry用于装饰自定义组件,表示自定义组件的入口,加了@Entry才能算是一个页面,否则只能算组件;
-
@State装饰器,使得变量变为状态变量,影响UI(数据变化,UI变化)
-
@Prop装饰的变量和父组件建立单向的同步关系:
-
父组件的@State数据变化,会同步到子组件@Prop
-
具体用法
-
//父组件:Parent
@State num:number = 0
build(){
Son({num:this.num})
}
//子组件:Son
@Prop num:number
-
@State修饰的变量,api9不能初始化,api11能初始化
-
@Link装饰的变量与其父组件中的数据源共享相同的值。
-
父组件的@State数据变化,会同步到子组件@Link数据
-
子组件@link数据变化,会同步到父组件@State数据
-
具体用法
-
//父组件:Parent
@State num:number = 0
build(){
Son({num:$num})//api9必须使用$,api11开始也可以使用this了
}
//子组件:Son
@Link num:number
-
@Link修饰的变量,api9不能初始化,api11能初始化
-
@Styles装饰器:定义组件重用样式 (多个组件通用的样式),用于封装重复的通用样式代码。
如果多个不同类型的组件,有着相同的样式,例如宽高,背景色,字体大小。那么就可以将这下相同的样式代码抽取到一个@Styles装饰器修饰的方法中,供大家复用。
支持全局和局部定义:
// 全局
@Styles function functionName() { ... } //styles方法不能调用另一个styles方法***
// 在组件内
@Component
struct FancyUse {
@Styles fancy() {
.height(100)
}
}
-
@Extend装饰器:定义扩展组件样式 (某一种组件自己的样式,私有属性),用于扩展原生组件样式。
如果同一类型的组件,有着很多相同的样式,例如按钮的类型,点击事件等。那么就可以将这些重复代码,抽过去到一个@Extend装饰器修饰的方法中,供此组件使用。
==仅支持全局定义==:(因为它相当于是给所有的此类组件使用)
// @Extend(Text)可以支持Text的私有属性fontColor
@Extend(Text) function fancy () {
.fontColor(Color.Red)
}
// superFancyText可以调用预定义的fancy
@Extend(Text) function superFancyText(size:number) { //Extend方法可以调用另一个Extend方法
.fontSize(size)
.fancy()
}
-
@Builder装饰器:自定义构建函数
@Builder装饰器,用于封装重复的,复杂UI结构代码,例如List中的ListItem的布局结构,一般比较复杂就可以抽取到@Builder装饰的函数中
@Builder所装饰的函数遵循build()函数语法规则,开发者可以将重复使用的UI元素抽象成一个方法,在build方法里调用。
支持全局定义和局部定义:
//既然调用是通过this调用,那么说明是在组件内部定义
//组件内部定义不需要关键字function
@Builder MyBuilderFunction() { ... }
//全局定义
MyGlobalBuilderFunction()
-
@BuilderParam装饰器:引用@Builder函数
当开发者创建了自定义组件,并想对该组件添加特定功能时,例如在自定义组件中添加一个点击跳转操作。若直接在组件内嵌入事件方法,将会导致所有引入该自定义组件的地方均增加了该功能。
为解决此问题,ArkUI引入了@BuilderParam装饰器,该装饰器用于声明任意UI描述的一个元素,==类似slot占位符==。
- 使得自定义组件更加灵活
代码:
@Component
struct Child {
@Builder customBuilder() {}
// 使用父组件@Builder装饰的方法初始化子组件@BuilderParam
@BuilderParam customBuilderParam: () => void = this.customBuilder;
build() {
Column() {
this.customBuilderParam()
}
}
}
@Entry
@Component
struct Parent {
@Builder componentBuilder() {
Text(`Parent builder `)
}
build() {
Column() {
Child({ customBuilderParam: this.componentBuilder })
}
}
}
-
Provide和Consume
@Provide和@Consume,用于祖先与后代组件的双向数据同步,实现跨层级传递
- ==理解==:@Provide装饰器的变量是在祖先组件中,可以理解为被“提供”给后代的状态变量。@Consume装饰的变量是在后代组件中,去“消费”数据
语法特点:
-
@Provide和@Consume可以通过相同的变量名或者相同的变量别名绑定
// 通过相同的变量名绑定
@Provide a: number = 0; //祖先组件中定义
@Consume a: number; //子孙组件中定义
// 通过相同的变量别名绑定
@Provide('a') b: number = 0;//参数即为别名
@Consume('a') c: number;
-
ObjectLink和Observed
@ObjectLink和@Observed类装饰器用于在涉及嵌套对象或数组的场景中进行双向数据同步:
- 被@Observed装饰的类,可以被观察到属性的变化;
- 子组件中@ObjectLink装饰器装饰的状态变量用于接收@Observed装饰的类的实例,和父组件中对应的状态变量建立双向数据绑定。这个实例可以是数组中的被@Observed装饰的项,或者是class object中的属性,这个属性同样也需要被@Observed装饰。
- 单独使用@Observed是没有任何作用的,需要搭配@ObjectLink或者@Prop使用。
-
Watch
概述
@Watch应用于==对状态变量的监听==。如果开发者需要关注某个状态变量的值是否改变,可以使用@Watch为状态变量设置回调函数。
@Watch用于监听状态变量的变化,当状态变量变化时,@Watch的回调方法将被调用
代码:
@Component
struct TotalView {
@Prop @Watch('onCountUpdated') count: number = 0;
@State total: number = 0;
// 该函数是自定义组件的成员函数
// @Watch 回调
// propName是被watch的属性名
// 多个状态绑定同一个@Watch回调时,通过propName区分到底是哪个状态改变了
onCountUpdated(propName: string): void {
this.total += this.count;
}
build() {
Text(`Total: ${this.total}`)
}
}
@Entry
@Component
struct CountModifier {
@State count: number = 0;
build() {
Column() {
Button('add to basket')
.onClick(() => {
this.count++
})
TotalView({ count: this.count })
}
}
}
其它:
- @CustomDialog:自定义弹窗,结合CustomDialogController使用。
- @Preview:用于预览器预览页面。
- @Reusable:复用标识,用于划分自定义组件的复用组。当组件回收复用时,复用框架将根据组件的reuseId来划分组件的复用组。从API Version 10开始支持。
- @Concurrent装饰器:校验并发函数。在使用TaskPool时,执行的并发函数需要使用该装饰器修饰,否则无法通过相关校验。
- @Track:应用于class对象的属性级更新。@Track装饰的属性变化时,只会触发该属性关联的UI更新。