在移动应用开发中,界面样式的一致性和开发效率是至关重要的。ArkUI 作为华为鸿蒙系统应用开发的重要框架,提供了强大的样式管理功能,其中 @Extend、@Styles 和 @Builder 在样式重用方面发挥着关键作用。合理运用这些特性,不仅能减少代码冗余,还能使界面风格更加统一,易于维护。本文将深入探讨这三个特性在 ArkUI 样式重用中的具体应用。

@Extend用于扩展特定组件的样式,支持参数传递,只能在全局定义。@Styles则是定义组件的重用样式,可以全局或局部定义,但无法传参。而@Builder是更轻量的UI元素复用机制,允许抽取结构、样式和事件,支持参数

1. @Extend

组件样式扩展
直接针对某个组件类型(如Text、Button)扩展样式,并支持通过参数动态调整样式属性,灵活性更高。

全局作用域
@Extend定义的样式默认全局可用,可在任意组件中调用,适合跨组件复用。

/*
 * 可以使用 @Extend来针对某个组件的属性和事件进行封装
 * 语法:@Extend(组件名) function 函数名称(参数1,参数2,...)
 *
 * 总结:
 * 1. @Extend作用是针对具体的某个组件进行扩展的
 * 2. 可以定义参数
 * 3. 可以对样式和事件进行封装扩展
 * 4. 可以在使用过程中被后面的属性进行覆盖
 *
 * 扩展:我想要给Button组件和Image组件进行扩展如何写?
 *  ✨✨注意:如果一个ets文件中针对了很多组件进行了扩展,
 * 某个组件只能使用自己的扩展,其他扩展方法使用不到
 * */
@Extend(Text)
function textExtend(fontsize:number,msg:string){
  .fontColor('rgba(0,0,0,0.7)')
  .fontSize(fontsize)
  .onClick(()=>{
    AlertDialog.show({message:msg})
  })
}

@Extend(Button) function buttonExtend(){
  .buttonStyle(ButtonStyleMode.TEXTUAL)
}

@Extend(Image) function imageExtend(){
 .fillColor(Color.Red)
}

@Entry
@Component
struct Index {
  build() {
    Column() {
      Row() {
        Text('浏览量 189')
          .textExtend(18,'我是第一个Text')
          .fontColor(Color.Red)

        Text('点赞 10')
          .textExtend(12,'我是第2个Text')
      }
    }
    .height('100%')
    .width('100%')

  }
}

注意:

① 扩展的组件和使用的组件同名,比如 @Extend(Text) ,那么后续通过 Text 才可以点出该扩展

② function 的名字不能与组件本身拥有的属性同名,自身属性优先级更高

例如:Text组件上本身自带有一个fontStyle属性,我们就不能再@Extend(Text) function fontStyle()一个同名方法了

③ 只能在当前组件有用,不能跨组件使用

2. @Styles

样式复用
将多个通用样式属性(如字体、颜色、边距等)封装成命名样式,通过名称调用,避免重复编写相同代码。

作用域分类

  • 全局样式:通过@Styles function定义,可在整个应用内复用
  • 组件私有样式:在组件内使用@Styles关键字定义,仅限当前组件使用

不支持参数传递
@Extend不同,@Styles无法动态接收参数,适合定义固定不变的通用样式规则。

不同组件,相同样式

/*
 * @Styles作用:可以封装通用的样式和通用的事件(可以给所有组件使用)
 * 语法:
 * 1. 全局
 *  @Styles function 函数名(){  }
 *
 * 2. 组件内(局部)
 *  @Styles  函数名(){  }
 *
 * 总结:
 * 1. @Styles作用和@Extend的作用区别:@Styles扩展通用属性和事件,@Extend扩展某个组件的属性和事件
 * 2. 语法上来对比@Styles可以全局定义和组件内定义,并且可以使用this,但是@Extend不能局部定义,不能使用this
 *
 * */

// 全局定义的函数中this用不了,需要改造成组件内的定义方式才可以使用this
@Styles function setCommonStyle(){
  .width(100)
  .height(100)
  .backgroundColor(Color.Gray)
  .onClick(()=>{
    AlertDialog.show({message:'OK'})
  })
}


@Entry
@Component
struct Day01_03_Styles {
  @State message: string = '@styles';
  @State bgColor: ResourceColor = Color.Gray

  // 定义局部的样式封装
  @Styles setStyle(){
    .width(100)
    .height(100)
    .backgroundColor(this.bgColor)
    .onClick(()=>{
      this.bgColor = Color.Orange
    })
  }

  build() {
    Column({ space: 10 }) {
      Text(this.message)
        // .setCommonStyle()  // 全局定义的使用
        .setStyle()   //局部定义的使用


      Column() {
      }
      // .setCommonStyle()
      .setStyle()


      Button('按钮')
        // .setCommonStyle()
        .setStyle()

    }
    .width('100%')
    .height('100%')
  }


}

3.@Builder

组件样式扩展
直接针对某个组件类型(如Text、Button)扩展样式,并支持通过参数动态调整样式属性,灵活性更高。

全局作用域
@Extend定义的样式默认全局可用,可在任意组件中调用,适合跨组件复用。

例如像这样,有两个文本,和事件,分别相同,将他抽取出来,可以使用Builder

@Builder
function GlobalTextItem(title: string) {
  Text(title)
    .fontSize(30)
    .onClick(() => {
      AlertDialog.show({message: '点击了'+title})
    })
}

@Entry
@Component
struct Day01_04_Builder {
  @State message: string = '@Builder';

  build() {
    Column({ space: 20 }) {
      // 使用全局 Builder
      GlobalTextItem('你好')

      // 使用本地 Builder
      this.LocalTextItem('西兰花炒蛋')
    }
    .width('100%')
    .height('100%')
  }
  // 本地声明
  @Builder
  LocalTextItem(title: string) {
    Text(title)
      .fontSize(30)
      .onClick(() => {
        AlertDialog.show({message: '点击了'+title})
      })
  }
}

4. @Extend、@Styles、@Builder 对比

适用HarmonyOS NEXT / API12或以上版本 -----------------

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐