HarmonyOS系统开发ArkTS常用组件编程技巧

目录

样式复用

@Styles方法

@Extend方法


组件编程在使用过程中有很多技巧,在这里分享样式复用技巧和UI结构复用技巧。

样式复用

我们观察下面的代码,在代码中很多重复行的代码,如:

复制代码
    Image 的  .width(30).height(30) 是重复的
    Button的  .fontSize(25).width(150).height(65).backgroundColor(Color.Green)是重复的
    Text  的  .fontSize(20).fontColor(Color.White).fontWeight(500) 是重复的
javascript 复制代码
@Entry
@Component
struct customStyle {
  @State isOn: boolean = false;
  @State isDel: boolean = false;

  build() {
    Column({ space: 10 }) {
      Button({ type: ButtonType.Capsule, stateEffect: true }) {
        Row({ space: 10 }) {
          Image($r('app.media.icon_new_folder'))
            .width(30)
            .height(30)
          Text('新建文件')
            .fontSize(20)
            .fontColor(Color.White)
            .fontWeight(500)
        }
      }
      .fontSize(25)
      .width(150)
      .height(65)
      .backgroundColor(Color.Green)
      .onClick(() => {
        console.log('我准备开始建立文件夹');
      })

      Button({ type: ButtonType.Capsule, stateEffect: true }) {
        Row({ space: 10 }) {
          Image($r('app.media.icon_new_folder'))
            .width(30)
            .height(30)
          Text('新建文件')
            .fontSize(20)
            .fontColor(Color.White)
            .fontWeight(500)
        }
      }
      .fontSize(25)
      .width(150)
      .height(65)
      .backgroundColor(Color.Green)
      .onClick(() => {
        console.log('我准备开始建立文件夹');
      })
    }
    .width('100%')
    .height("100%")
    .justifyContent(FlexAlign.Center)

  }
}


@Extend(Image) function consumeImgStyle() {
  .width(30)
  .height(30)
}

@Extend(Button) function consumeButtonStyle() {
  .fontSize(25)
  .width(150)
  .height(65)
}

@Extend(Text) function consumeBTextStyle() {
  .fontSize(20)
  .fontColor(Color.White)
  .fontWeight(500)
}

当多个组件具有相同的样式时,若每个组件都单独设置,将会有大量的重复代码。为避免重复代码,开发者可使用**@Styles或者@Extend装饰器**将多条样式设置提炼成一个方法,然后直接在各组件声明的位置进行调用,这样就能完成样式的复用。

@Styles方法

@Styles方法可定义在组件内 或者全局。

    1. 组件内定义的@Styles方法只能在当前组件中使用,全局的@Styles方法目前只允许在当前的.ets文件中使用
    1. 组件内定义@Styles方法时不需要使用function关键字,全局的@Styles方法需要使用function关键字
    1. @Styles方法中只能**包含通用属性方法和通用事件方法,**例如在上面的代码中 fontSize(20).fontColor(Color.White).fontWeight(500)也是重复的,但这不是通用属性。可以定义的只能是通用属性。
    1. @Styles方法不支持参数
    1. @Styles方法可以用在任意类型的组件上。注意下面的@Extend则是使用在定制化组件上。

将上面重复的样式代码分别提取到各自定义的@Style方法中,直接使用@Style方法

定义格式如下。

javascript 复制代码
@Styles定义在Struct结构体内部
===============================================================================
  @Styles consumeImgStyle(){
    .width(30)
    .height(30)
  }

  @Styles consumeButtonStyle(){
    .width(150)
    .height(65)
    .backgroundColor(Color.Green)
  }

@Styles定义在同一个ets文件中的Struct结构体外部,必须加上 function 关键字
===============================================================================

@Styles function globalConsumeImgStyle() {
  .width(30)
  .height(30)
}

@Styles function globalConsumeButtonStyle() {
  .width(150)
  .height(65)
  .backgroundColor(Color.Green)
}

将重复样式代码提取之后,直接使用提取后的方法,使用@Styles方法之后代码。

javascript 复制代码
@Entry
@Component
struct customStyle {
  @State isOn: boolean = false;
  @State isDel: boolean = false;

  build() {
    Column({ space: 10 }) {
      Button({ type: ButtonType.Capsule, stateEffect: true }) {
        Row({ space: 10 }) {
          Image($r('app.media.icon_delete'))
            .consumeImgStyle()
          Text('删除文件')
            .fontSize(20)
            .fontColor(Color.White)
            .fontWeight(500)
        }
      }
      .fontSize(25)
      .width(150)
      .height(65)

      Button({ type: ButtonType.Capsule, stateEffect: true }) {
        Row({ space: 10 }) {
          Image($r('app.media.icon_new_folder'))
            .consumeImgStyle()
          Text('新建文件')
            .fontSize(20)
            .fontColor(Color.White)
            .fontWeight(500)
        }
      }
      .consumeButtonStyle()
      .fontSize(25)
      .onClick(() => {
        console.log('我准备开始建立文件夹');
      })
    }
    .width('100%')
    .height("100%")
    .justifyContent(FlexAlign.Center)

  }

  @Styles consumeImgStyle(){
    .width(30)
    .height(30)
  }

  @Styles consumeButtonStyle(){
    .width(150)
    .height(65)
    .backgroundColor(Color.Green)
  }
}

定义全局使用的@Styles方法需要加 function
======================================================
@Styles function globalConsumeImgStyle() {
  .width(30)
  .height(30)
}

@Styles function globalConsumeButtonStyle() {
  .width(150)
  .height(65)
  .backgroundColor(Color.Green)
}

@Extend方法

@Extend装饰的方法同样可用于组件样式的复用,与@Styles不同的是:

  • @Extend方法只能定义在全局,使用范围目前只限于当前的.ets文件
  • @Extend方法只能用于指定类型的组件,如Button组件
  • @Extend方法可包含指定组件的专有属性方法和专有事件方法。
  • @Extend方法支持参数传递

重复的代码

Image 的 .width(30).height(30) 是重复的

Button的 .fontSize(25).width(150).height(65) .backgroundColor(Color.Green)是重复的

Text 的 .fontSize(20).fontColor(Color.White).fontWeight(500)是重复的

将上面重复的样式代码分别提取到各自定义的@Extend方法中,直接使用@Extend方法

定义格式如下。

javascript 复制代码
@Extend(Image) function consumeImgStyle() {
  .width(30)
  .height(30)
}

@Extend(Button) function consumeButtonStyle(color: Color) {
  .fontSize(25)
  .width(150)
  .height(65)
  .backgroundColor(color)

}

@Extend(Text) function consumeTextStyle(color: Color, size: number, weight: number) {
  .fontSize(size)
  .fontColor(color)
  .fontWeight(weight)
}

将重复样式代码提取之后,直接使用提取后的方法,使用@Extend方法之后代码。

javascript 复制代码
@Entry
@Component
struct customStyle {
  @State isOn: boolean = false;
  @State isDel: boolean = false;

  build() {
    Column({ space: 10 }) {
      Button({ type: ButtonType.Capsule, stateEffect: true }) {
        Row({ space: 10 }) {
          Image($r('app.media.icon_new_folder'))
            .consumeImgStyle()
          Text('新建文件')
            .consumeTextStyle(Color.White, 20, 500)
        }
      }
      .consumeButtonStyle(Color.Green)
      .onClick(() => {
        console.log('我准备开始建立文件夹');
      })

      Button({ type: ButtonType.Capsule, stateEffect: true }) {
        Row({ space: 10 }) {
          Image($r('app.media.icon_new_folder'))
            .consumeImgStyle()
          Text('新建文件')
            .consumeTextStyle(Color.White, 20, 500)
        }
      }
      .consumeButtonStyle(Color.Green)
      .onClick(() => {
        console.log('我准备开始建立文件夹');
      })
    }
    .width('100%')
    .height("100%")
    .justifyContent(FlexAlign.Center)
  }
}


@Extend(Image) function consumeImgStyle() {
  .width(30)
  .height(30)
}

@Extend(Button) function consumeButtonStyle(color: Color) {
  .fontSize(25)
  .width(150)
  .height(65)
  .backgroundColor(color)

}

@Extend(Text) function consumeTextStyle(color: Color, size: number, weight: number) {
  .fontSize(size)
  .fontColor(color)
  .fontWeight(weight)
}

UI结构复用

当页面有多个相同的UI结构时,若每个都单独声明,同样会有大量重复的代码。为避免重复代码,可以将相同的UI结构提炼为一个自定义组件,完成UI结构的复用。

除此之外,ArkTS还提供了一种更轻量的UI结构复用机制@Builder方法,开发者可以将重复使用的UI元素抽象成一个@Builder方法,该方法可在build()方法中调用多次,以完成UI结构的复用。

@Builder装饰的方法同样可用于组件接结构的复用,

  • @Builder方法可以定义在组件内或者全局
  • @Builder方法定义的是组件内的@Builder方法,可通过this访问当前组件的属性和方法,而全局的@Builder方法则不能
  • @Builder方法定义的是组件内的@Builder方法只能用于当前组件,全局的@Builder方法导出(export)后,可用于整个应用。
javascript 复制代码
@Entry
@Component
struct BuilderUI {
  @State isOn: boolean = false;
  @State isDel: boolean = false;

  build() {
    Column({ space: 10 }) {
      this.builderButton($r('app.media.icon_delete'), '删除文件', () => {
        console.log('我准备开始删除文件夹');
      })
      globalBuilderButton($r('app.media.icon_new_folder'), '新建文件', () => {
        console.log('我准备开始建立文件夹');
      })
    }
    .width('100%')
    .height("100%")
    .justifyContent(FlexAlign.Center)
  }

  @Builder builderButton(icon: Resource, text: string, callback: () => void) {
    Button({ type: ButtonType.Capsule, stateEffect: true }) {
      Row({ space: 10 }) {
        Image(icon)
          .width(30)
          .height(30)
        Text(text)
          .fontSize(20)
          .fontColor(Color.White)
          .fontWeight(500)
          .backgroundColor(Color.Green)
      }
    }
    .fontSize(25)
    .width(150)
    .height(65)
    .onClick(callback)
  }
}

@Builder function globalBuilderButton(icon: Resource, text: string, callback: () => void) {
  Button({ type: ButtonType.Capsule, stateEffect: true }) {
    Row({ space: 10 }) {
      Image(icon)
        .width(30)
        .height(30)
      Text(text)
        .fontSize(20)
        .fontColor(Color.White)
        .fontWeight(500)
        .backgroundColor(Color.Green)
    }
  }
  .fontSize(25)
  .width(150)
  .height(65)
  .onClick(callback)
}
  • @Builder方法支持参数传递规则,分为按值传递和按引用传递。带有花括号的{ } 为引用传递,其余为值传递。
  • 按引用传递时,若传递的参数为状态变量,则状态变量的变化将会触发@Builder方法内部UI的刷新,而按值传递时则不会。
javascript 复制代码
@Entry
@Component
struct BuilderUI {
  @State status: number = 10;

  build() {
    Column({ space: 10 }) {
      valueText(this.status)
      referenceText({status:this.status})

      Row({ space: 10 }) {
        Button('值传递 - 1')
          .consumeButtonStyle()
          .onClick(() => {
            this.status--
          })
        Button('引用传递 + 1')
          .consumeButtonStyle()
          .onClick(() => {
            this.status++
          })
      }
    }
    .width('100%')
    .height("100%")
    .justifyContent(FlexAlign.Center)
  }


}

@Builder function valueText(count: number) {
  Text(`进行值传递:  ${count}`).fontSize(30).fontWeight(600)
}

@Builder function referenceText(count: {status:number}) {
  Text(`进行引用传递: ${count.status}`).fontSize(30).fontWeight(600)
  Text('引用参数传递的是状态变量status,这里内部UI会刷新')
}

@Extend(Button) function consumeButtonStyle() {
  .fontSize(20)
  .width(140)
  .height(65)
}
相关推荐
遇到困难睡大觉哈哈2 小时前
HarmonyOS 应用数据持久化概述:Preferences、KV-Store、RelationalStore 到底怎么选?
笔记·华为·harmonyos
宇擎智脑科技2 小时前
Flutter 对接高德地图 SDK 适配鸿蒙踩坑记录与通信架构解析
flutter·架构·harmonyos
嗝o゚3 小时前
鸿蒙智慧屏与Flutter适配:无硬件功能的兼容处理
flutter·华为·开源·harmonyos
luxy20043 小时前
HarmonyOS简易时钟应用
华为·harmonyos
俩毛豆4 小时前
基于HarmonyOS(NEXT)的超级App中的搜索架构实现(直播文字干货版)
成长·架构·app·harmonyos·搜索
嗝o゚4 小时前
Flutter 无障碍功能开发最佳实践
python·flutter·华为
嗝o゚6 小时前
开源鸿蒙 Flutter 应用包瘦身实战
flutter·华为·开源·harmonyos
云和数据.ChenGuang6 小时前
鸿蒙负一屏的技术定位与核心价值
华为·wpf·harmonyos
遇到困难睡大觉哈哈9 小时前
HarmonyOS 关系型数据库 RDB 数据持久化(ArkTS)实战:建库建表、CRUD、事务、FTS、性能优化,一篇搞懂
笔记·华为·harmonyos
嗝o゚11 小时前
Flutter适配鸿蒙多屏异构UI开发实战
flutter·开源·wpf·harmonyos