装饰器@Builder
也是用来定义组件,功能类似@Component的基础使用,使用更轻便灵活,但功能比较单一,不支持状态装饰器(上一篇内容),换句话说就是不支持和父组件有交互。使用有以下特性
- 有两种用法:全局的,组件内部的。
- 有两种传参方式:按值传递参数,按引用传递参数。
两种类型
作用域的区别,全局使用和组件内部使用
// 全局自定义函数组件
@Builder outBuilder(){
Row() {
Text(`outBuilder`)
}
}
@Entry
@Component
struct Index {
// 组件内部函数组件
@Builder inBuilder(){
Row() {
Text(`inBuilder`)
}
}
build() {
Row(){
outBuilder()
this.inBuilder()
}
}
}
两种传参方式
可以参考数据结构中的基础类型和引用类型。
- 按值传递:值不再响应传参的变化。
- 按引用传递:值会响应传参的变化。
// 按值传递参数
@Builder cusBuilder1(p1: string){
Row() {
Text(`Builder${p1}`) // 不会响应父组件msg的值的改变
}
}
// 按引用传递参数
@Builder cusBuilder2($$: {p2: string}){
Row() {
Text(`Builder${$$.p2}`) // 会响应父组件msg的值的改变
}
}
@Entry
@Component
struct Index {
@State msg: string = '1'
build() {
Row(){
cusBuilder1(this.msg)
cusBuilder2({p2: this.msg})
Button(`按钮`)
.onClick(() => {
this.msg = '2'
})
}
}
}
有没有react中函数组件和Class组件的赶脚。
扩展用法
内部函数组件猛的一看有点鸡肋,但因为是在组件内部是可以直接调用组件内部的变量。这样既可以抽离出一部分复杂的东西,又不用考虑变量的传值
@Entry
@Component
struct Index {
@State msg: string = '1'
// 组件内部函数组件
@Builder inBuilder(){
Row() {
Text(`inBuilder${this.msg}`)
}
}
build() {
Row(){
this.inBuilder()
Button(`按钮`)
.onClick(() => {
this.msg = '2'
})
}
}
}
装饰器@Styles
@Style装饰器是提炼公共样式进行复用的装饰器。之前说过样式都是绑定在组件上链式调用,复杂的功能就会很臃肿,且可能会有一些重复的样式。@Style就是用来解决这些问题的。使用有以下特性
- 有全局和组件内部两种类型,且组件内部定义的优先级高于全局
- 不支持传参,但组件内部定义的可以调用组件变量
// 定义在全局的@Styles封装的样式
@Styles function globalFancy () {
.width(150)
.height(100)
.backgroundColor(Color.Pink)
}
@Entry
@Component
struct FancyUse {
@State heightValue: number = 100
// 定义在组件内的@Styles封装的样式
@Styles fancy() {
.width(200)
.height(this.heightValue)
.backgroundColor(Color.Yellow)
.onClick(() => {
this.heightValue = 200
})
}
build() {
Column({ space: 10 }) {
Text('FancyA')
.globalFancy() // 使用全局的@Styles封装的样式
.fancy() // 使用组件内的@Styles封装的样式
.fontSize(30)
}
}
}
装饰器@Extend
@Extend是用于扩展原生组件样式的装饰器。测试使用下来的感觉就是弥补了@Style全局模式不能传参的缺点。有以下特性
- 是对鸿蒙原生组件进行扩展,指定绑定在扩展的对应原生组件上
- 仅支持全局定义
- 传值的方式传变量也是可以响应式的
@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 // UI可以响应更新
})
}
}
}
补充:在后续测试中发现很多属性不属于通用元素属性,在@Styles中是无法提取的。比如fontColor、fontSize只有在类似Text这种元素组件上可用,如果在@Styles声明就会报错