ArkTs-装饰器

组件样式复用

@Styles和@Extend

将多条样式设置提炼成一个方法,然后在各个组件声明的位置进行调用,完成样式的复用

@style

可定义在组件内或全局,只能包含通用属性,不能传参

@Entry
@Component
struct Index{
  @State num:number = 1
  build() {
    Column(){
      Row({space:50}){
        Button('确认')
          .type(ButtonType.Normal)
          .backgroundColor(Color.Green)
          .comButtonStyle()//复用样式
          .onClick(()=>console.log('点击确认键'))
        Button('取消')
          .type(ButtonType.Normal)
          .backgroundColor(Color.Gray)
          .comButtonStyle()
          .onClick(()=>console.log('点击取消键'))
      }
    }
    .width('100%')
    .height('100%')
    .justifyContent(FlexAlign.Center)
  }
  //组件内定义
  @Styles comButtonStyle(){
    .width(100)
    .height(40)
    .borderRadius(10)
  }
}
// 全局定义样式,在当前页面中全局可用
@Styles
function globalButtonStyle( ) {
  .width(100)
  .height(40)
  .borderRadius(10)
}

@Extend

同样可以用于组件样式的复用,与@Styles不同的是,@Extend只能定义在全局,且只能用于指定类型的组件

如下可以理解为Button组件的样式拓展,方法中可能包含指定组件专有属性专有方法



@Entry
@Component
struct Index{
  @State num:number = 1
  build() {
    Column(){
      Row({space:50}){
        Button('确认')
          .type(ButtonType.Normal)
          .backgroundColor(Color.Green)
          .comButtonStyle()//复用样式
          .onClick(()=>console.log('点击确认键'))
        Button('取消')
          .buttonExtendStyle(Color.Gray,()=>{
            console.log('点击取消键');
          })
      }
    }
    .width('100%')
    .height('100%')
    .justifyContent(FlexAlign.Center)
  }
  //组件内定义
  // 不能有参数
  @Styles comButtonStyle(){
    // .backgroundColor(color)
    .width(100)
    .height(40)
    .borderRadius(10)
  }
}
// 全局定义样式
@Styles
function globalButtonStyle( ) {
  .width(100)
  .height(40)
  .borderRadius(10)
}
@Extend(Button)
function buttonExtendStyle(color:Color,callback:()=>void ) {
  .width(100)
  .height(40)
  .borderRadius(10)
  .type(ButtonType.Capsule)
  .backgroundColor(color)
  .onClick(callback)
}

UI结构复用

@Builder方法

除自定义组件外,arkTS提供了更加轻量的UI结构的复用机制,@Builder方法

可声明在组件内或全局

1、组件内的@Builder方法,通过this调用,只能用于当前组件, 

2、全局的@Builder方法,不用通过this调用,导出(export)之后,可用于整个应用


@Entry
@Component
struct Index{
  @State num:number = 1
  build() {
    Column(){

      Row({space:50}){
        Button('确认')
          .type(ButtonType.Normal)
          .backgroundColor(Color.Green)
          .comButtonStyle()//复用样式
          .onClick(()=>console.log('点击确认键'))
        Button('取消')
          .buttonExtendStyle(Color.Gray,()=>{
            console.log('点击取消键');
          })
      }
      Button(){
        Row(){
          Image($r('app.media.app_icon'))
            .width(25)
            .height(25)
          Text('发送')
            .fontSize(25)
            .fontColor(Color.White)
        }
      }
      .width(120)
      .height(50)
      .onClick(()=>{console.log('发送')})
      this.compButtonBuilder($r('app.media.app_icon'),'send',()=>console.log('send'))
    }
    .width('100%')
    .height('100%')
    .justifyContent(FlexAlign.Center)
  }
  //组件内定义
  // 不能有参数
  @Styles comButtonStyle(){
    // .backgroundColor(color)
    .width(100)
    .height(40)
    .borderRadius(10)
  }
  @Builder compButtonBuilder(icon:Resource,text:string,callback:()=>void){
    Button(){
      Row(){
        Image($r('app.media.app_icon'))
          .width(25)
          .height(25)
        Text(text)
          .fontSize(25)
          .fontColor(Color.White)
      }
      .width(120)
      .height(50)
      .onClick(callback)
    }
  }
}
// 全局定义样式
@Styles
function globalButtonStyle( ) {
  .width(100)
  .height(40)
  .borderRadius(10)
}
@Extend(Button)
function buttonExtendStyle(color:Color,callback:()=>void ) {
  .width(100)
  .height(40)
  .borderRadius(10)
  .type(ButtonType.Capsule)
  .backgroundColor(color)
  .onClick(callback)
}

@Builder
export function compButtonBuilder(icon:Resource,text:string,callback:()=>void ) {
    Button(){
      Row(){
        Image($r('app.media.app_icon'))
          .width(25)
          .height(25)
        Text(text)
          .fontSize(25)
          .fontColor(Color.White)
      }
      .width(120)
      .height(50)
      .onClick(callback)
    }
}

@Builder方法参数传递规则

当以对象字面量的方式传值,若传递的参数为状态变量,则状态变量的变化会引起@Builder方法内部UI刷新,按传递则不会

@Builder与自定义组件的区别

1、都可以实现UI复用的效果,

2、自定义组件可以定义自己的状态变量,而@Builder方法不能

如:todolist,需要给每个待办事项都定义一个状态变量,此时只能用自定义组件实现。

@BuilderParam

 用于装饰自定义组件(struct)中的属性,其装饰的属性可作为一个UI结构的占位符

创建该组件时,可通过参数为其传入具体的内容(类似于Vue中的slot)

@Component
struct Child {
  // 使用父组件@Builder装饰的方法初始化子组件@BuilderParam
  @BuilderParam customBuilderParam: () => void;

  build() {
    Column() {
      this.customBuilderParam()
    }
  }
}

@Entry
@Component
struct Parent {
  @Builder componentBuilder() {
    Text(`Parent builder `)
  }

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

状态管理 

@State

用于修饰当前组件的状态变量,@State修饰的变量发生改变时,会驱动当前组件的试图刷新

@State修饰的变量必须进行本地初始化

@State count:number = 0

1、@State允许修饰的变量类型有string、number、boolean、object、enum、class

2、框架能够观察到的变化,不是@state变量的所有更改都会引起UI的刷新,只有可以被框架观察到的修改才会引起UI的刷新:boolean、string、number

3、@State修饰的变量为class和Object时,可以观察到变量自身赋值的变化,嵌套属性的变化是观察不到的

4、当@State装饰的变量为数组时,可以观察到元素本身赋值、元素添加、删除及更新的变化,若元素类型为class/object时,元素属性的变化时观察不到的

**变量为class/Object/数组时框架仅能观察到@State变量第一层属性的变化

@Prop

除了与@State相同的作用外,@Prop装饰的变量还可以同步父组件中的状态变量,且只能单向同步,子组件的变化不会同步到父组件  

目前只支持简单数据类型:string/number/boolean/enum

@prop装饰的变量不允许初始化,只能通过父组件向子组件传参进行初始化

struct  Parent{
  @State count:number = 1
  build() {
    Column(){
      Child({count:$count})
    }
  }
}

@Component
struct Child{
  @Prop count:number
  build() {
    Text(this.count.toString())
  }
}

@Link 

除了与@State相同的作用外,@Link同样会同步父组件状态,并且能够双向同步

@Link装饰的变量不允许本地初始化,只能由父组件通过传参进行初始化,父组件必须使用$变量名的方式传参


struct  Parent{
  @State count:number = 1
  build() {
    Column(){
      Child({count:$count})
    }
  }
}

@Component
struct Child{
  @Link count:number
  build() {
    Text(this.count.toString())
  }
}

@Provide和@Conmuse

可用于跨组件层级传递状态信息

其中,@Provide用于装饰祖先组件的状态变量,@Conmuse用于修饰后代组件的状态变量。

祖先组件提供Provide状态信息供后代组件消费,

并且祖先和后代的状态信息可双向同步

@Provide装饰变量必须进行本地初始化,而@Conmuse装饰的变量不允许进行本地初始化

struct GrandParent{
  @Provide count:number = 1
  // 别名
  // @Provide('count') ParentContent:number = 1
  build() {
    Column(){
      Parent()
    }
  }
}
@Component
struct  Parent{
  build(){
    Column(){
      Child()
    }
  }
}

@Component
struct  Child{
  @Consume count:number;
  // 通过变量的别名进行绑定
  // @Consume('count') childCount:number
  build() {
    Column(){
      Text(this.count.toString())
    }
  }
}

@ObjectLink和@Observed 

 解决只能观察到第一层属性变化的问题

修改嵌套对象写法会让页面刷新,需要重新赋值整个项,才能检测到变化,使页面重新刷新,降低用户体验。

  • 11
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 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
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值