Arkts--装饰器

在这里插入图片描述

示例

这是一个 @Builder值传参 示例:

@Entry
@Component
struct C_Builder{
  @State label:string = "hello builder";
  @State hint:string = "";
    build() {
        Tabs(){
            ……
            TabContent(){
                    Column() {
                      overBuilder2(this.label)
                      Text(this.hint).margin({top:20,bottom:20})
                      Button('Click me').onClick(() => {
                        this.label = 'ArkUI';
                        this.hint = 'Button事件触发,但是overBuilder的内容并未因label的改变而改变 this.label = '+this.label;
                      })
                    }.width("100%")
              .height("100%")
            }.tabBar("值传递")
        }

    }
}
@Builder function overBuilder2(paramA1: string) {
  Row() {
    Text(`UseStateVarByReference: ${paramA1} `)
  }
}

装饰器使用说明

@BuilderParam装饰器:引用@Builder函数

场景: 当开发者创建了自定义组件,并想对该组件添加特定功能时,例如在自定义组件中添加一个点击跳转操作。若直接在组件内嵌入事件方法,将会导致所有引入该自定义组件的地方均增加了该功能。

作用: ArkUI引入了@BuilderParam装饰器,@BuilderParam用来装饰指向@Builder方法的变量,开发者可在初始化自定义组件时对此属性进行赋值,为自定义组件增加特定的功能。该装饰器用于声明任意UI描述的一个元素,类似slot占位符。

帮助理解: 相当于有N个人都要看书,大家都是用眼睛看,但是突然有一个盲人出现了,这个时候用眼睛看书已经不实际了,盲人靠手的触摸看的也是盲文,有点类似与java的重写,但这个允许人不看书。

尾随闭包初始化组件

  • 在自定义组件中使用@BuilderParam装饰的属性时也可通过尾随闭包进行初始化。在初始化自定义组件时,组件后紧跟一个大括号“{}”形成尾随闭包场景。
  • 在这个示例进行了展示:
@Component
struct ReadBooks{
  @Prop bookType:string ;
  @BuilderParam readBook:() => void;
  build(){
    Column(){
      Text(this.bookType)
      this.readBook()
    }
  }
}

@Entry
@Component
struct People{
  @State bookType : string = "正常人看正常书";
  @State btc :string = "盲人"
  build(){
    Column(){
      Button(this.btc).onClick(()=>{
        if (this.btc == "盲人") {
          this.bookType = "盲人看盲文";
          this.btc = "正常人"
        }else {
          this.bookType = "正常人看正常书";
          this.btc = "盲人"
        }
      })
      ReadBooks({bookType:this.bookType}){
        Column(){
          Text("看书中……")
        }
      }
    }.width("100%").alignSelf(ItemAlign.Center)
  }
}

参数初始化组件

  • @BuilderParam装饰的方法可以是有参数和无参数的两种形式,需与指向的@Builder方法类型匹配。@BuilderParam装饰的方法类型需要和@Builder方法类型一致。
@Builder function overBuilder($$ : {label: string }) {
  Text($$.label)
    .width(400)
    .height(50)
    .backgroundColor(Color.Green)
}

@Component
struct Child {
  label: string = 'Child'
  // 无参数类型,指向的componentBuilder也是无参数类型
  @BuilderParam customBuilderParam: () => void;
  // 有参数类型,指向的GlobalBuilder1也是有参数类型的方法
  @BuilderParam customOverBuilderParam: ($$ : { label : string}) => void;

  build() {
    Column() {
      this.customBuilderParam()
      this.customOverBuilderParam({label: 'global Builder label' } )
    }
  }
}

@Entry
@Component
struct Parent {
  label: string = 'Parent'

  @Builder componentBuilder() {
    Text(`${this.label}`)
  }

  build() {
    Column() {
      this.componentBuilder()
      Child({ customBuilderParam: this.componentBuilder, customOverBuilderParam: overBuilder })
    }
  }
}

在这里插入图片描述

@Styles装饰器:定义组件重用样式

  • 如果每个组件的样式都需要单独设置,在开发过程中会出现大量代码在进行重复样式设置,虽然可以复制粘贴,但为了代码简洁性和后续方便维护,我们推出了可以提炼公共样式进行复用的装饰器@Styles。

  • @Styles装饰器可以将多条样式设置提炼成一个方法,直接在组件声明的位置调用。通过@Styles装饰器可以快速定义并复用自定义样式。用于快速定义并复用自定义样式。

装饰器使用说明

  • 当前@Styles仅支持通用属性和通用事件。
  • @Styles方法不支持参数。
  • @Styles可以定义在组件内或全局,在全局定义时需在方法名前面添加function关键字,组件内定义时则不需要添加function关键字。
  • 只能在当前文件内使用,不支持export。
  • 定义在组件内的@Styles可以通过this访问组件的常量和状态变量,并可以在@Styles里通过事件来改变状态变量的值,注意:组件的onClick优先于@Styles里的onClick,并且只响应优先级高的
  • 组件内@Styles的优先级高于全局@Styles。框架优先找当前组件内的@Styles,如果找不到,则会全局查找。
/// 定义在全局的@Styles封装的样式
@Styles function globalFancy  () {
  .width(150)
    .height(100)
    .backgroundColor(Color.Pink)
}

@Entry
@Component
struct C_Styles {
  @State heightValue: number = 50
  // 定义在组件内的@Styles封装的样式
  @Styles fancy() {
    .width(200)
    .height(this.heightValue)
    .backgroundColor(Color.Yellow)
    .onClick(() => {
      if (this.heightValue == 50) {
        this.heightValue = 100
      }else {
        this.heightValue = 50
      }

    })
  }

build() {
    Column({ space: 10 }) {
      // 使用全局的@Styles封装的样式
      Text('FancyA')
        .globalFancy()
        .fontSize(30)
      // 使用组件内的@Styles封装的样式
      Text('FancyB')
        .fancy()
        .fontSize(30)
      // 点击C 会发现B的高度发生了改变,也就是当同事引用多个样式时,框架会对其取并集
      Text('FancyC')
        .fancy()
        .globalFancy()
        .fontSize(30)
      Button("测试")
        .fancy()
        .fontColor(Color.Black)
        .fontSize(30)
        .onClick(()=>{
          AlertDialog.show({
            title:"事件",
            message:"测试按钮事件触发"
          })
        })
    }
}
}

@Extend装饰器:定义扩展组件样式

在前文的示例中,可以使用@Styles用于样式的扩展,在@Styles的基础上,华为提供了@Extend,用于扩展原生组件样式。

语法

@Extend(UIComponentName) function functionName { ... }

使用规则

  • 和@Styles不同,@Extend仅支持定义在全局,不支持在组件内部定义。
  • 和@Styles不同,@Extend支持封装指定的组件的私有属性和私有事件和预定义相同组件的@Extend的方法。
  • 和@Styles不同,@Extend装饰的方法支持参数,开发者可以在调用时传递参数,调用遵循TS方法传值调用。
  • @Extend装饰的方法的参数可以为function,作为Event事件的句柄。
  • @Extend的参数可以为状态变量,当状态变量改变时,UI可以正常的被刷新渲染。
示例

// @Extend(Text)可以支持Text的私有属性fontColor
@Extend(Text) function fancy () {
  .fontColor(Color.Red)
}
// superFancyText可以调用预定义的fancy
@Extend(Text) function superFancyText(size:number) {
  .fontSize(size)
  .fancy()
}
//@Extend装饰的方法的参数可以为function,作为Event事件的句柄。
@Extend(Text) function makeMeClick(onClick: () => void) {
  .backgroundColor(Color.Grey)
  .onClick(onClick)
}

@Entry
@Component
struct FancyUse {
  @State label: string = 'Hello World';
  @State label2: string = 'Hello World';
  @State fontSizeValue: number = 30
  onClickHandler() {
    if (this.label.includes('World')) {
      this.label = 'Hello ArkUI';
    }else {
      this.label = 'Hello World';
    }
  }

  build() {
    Column({ space: 10 }) {
      Text('Fancy0')
        .fancy()
      Text('Fancy1')
        .superFancyText(24)
      Text('Fancy2')
        .superFancyText(28)
      Text('Fancy3')
        .superFancyText(this.fontSizeValue)
        .onClick(()=>{
          if (this.fontSizeValue == 30) {
            this.fontSizeValue = 35;
          }else {
            this.fontSizeValue = 30;
          }
        })
      Text(`${this.label}`)
        //this.onClickHandler.bind(this) 是用来绑定 FancyUse 组件实例的 onClickHandler 方法的,以确保在 onClickHandler 方法中 this 的指向正确。
        //然后,这个绑定后的函数作为参数传递给了 makeMeClick 方法,使得当 Text 组件被点击时,会调用 onClickHandler 方法,并且在正确的上下文中执行。
        .makeMeClick(this.onClickHandler.bind(this))
      // 优先组件的onClick,且只响应优先级别高的
      Text(`${this.label2}`)
        .makeMeClick(this.onClickHandler.bind(this))
        .onClick(()=>{
          this.label2 = 'Hello onClick';
        })
    }.width("100%")
  }
}

在这里插入图片描述

stateStyles:多态样式

stateStyles(又称为:多态样式)针对:@Styles和@Extend仅仅应用于静态页面的样式复用,stateStyles可以依据组件的内部状态的不同,快速设置不同样式。

概述

stateStyles是属性方法,可以根据UI内部状态来设置样式,类似于css伪类,但语法不同。ArkUI提供以下四种状态:

  • focused:获焦态。
  • normal:正常态。
  • pressed:按压态。
  • disabled:不可用态。
示例

//在stateStyles里不能进行引用,会报错:.stateStyles doesn't conform standard.
@Styles function  normalStyle(){
  .backgroundColor(Color.Gray)
}
@Extend(Text) function normalExtend(size:number){
  .fontSize(size)
}


@Entry
@Component
struct C_stateStyles{

  @Styles pressedStyle() {
    .backgroundColor(Color.Red)
  }
  @Styles normalStyle(){
  .backgroundColor(Color.Gray)
}
  build(){
    Column() {
      Button('Button1')
        .stateStyles({
          focused: {
            .backgroundColor(Color.Pink)
          },
          pressed: {
            .backgroundColor(Color.Black)
          },
          normal: {
            .backgroundColor(Color.Red)
          }
        })
        .margin(20)
      Button('Button2')
        .stateStyles({
          pressed:this.pressedStyle,
          normal:this.normalStyle
        })
    }.margin('30%')
  }
}
  • 22
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
object literals cannot be used as type declarations (arkts-no-obj-literals-a) 是指在 TypeScript 中,不能将对象字面量用作类型声明。 在 TypeScript 中,我们可以使用类型声明来定义变量、参数和函数的类型。类型声明允许我们指定变量的类型,以便在编译时进行类型检查,并提供更好的代码提示和静态分析。 然而,当我们尝试使用对象字面量作为类型声明时,TypeScript 会出现错误消息 "object literals cannot be used as type declarations (arkts-no-obj-literals-a)"。这是因为对象字面量通常用于创建对象而不是定义类型。 例如,下面的代码尝试使用对象字面量作为类型声明: ```typescript const user: { name: string, age: number } = { name: "Alice", age: 25 }; ``` 上述代码会导致错误,因为对象字面量不能被用作类型声明。为了解决这个问题,我们可以使用 interface 或 type 关键字来定义类型: ```typescript interface User { name: string, age: number } const user: User = { name: "Alice", age: 25 }; ``` 在上述代码中,我们使用 interface 关键字定义了一个名为 User 的接口,它包含了 name 和 age 两个属性。接着,我们使用 User 接口作为类型声明,来定义 user 变量的类型。 总结来说,"object literals cannot be used as type declarations (arkts-no-obj-literals-a)" 是 TypeScript 中的错误消息,意味着不能直接使用对象字面量作为类型声明,而应该使用接口或类型声明来定义对象的类型。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

星辰yzy

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值