首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >鸿蒙Next 组件样式封装

鸿蒙Next 组件样式封装

原创
作者头像
用户4773577
修改2025-06-28 20:54:22
修改2025-06-28 20:54:22
9700
代码可运行
举报
运行总次数:0
代码可运行

封装!封装!封装!

不会封装的Coder不是一个好CV大师

当我们的布局中有比较多的重复样式需要设置时,会增加很多相同类似的代码,增加维护成本,组件的抽离和复用是非常重要的,记下来举个例子。

如果实现上面一个用户中心的卡片列表,先举一个反面例子

代码语言:javascript
代码运行次数:0
运行
复制
@Entry
@ComponentV2
struct User{
  build() {
    Column(){
      Column(){
        RelativeContainer(){
          Row({space:20}){
            Image($r('app.media.ic_my_card')).width(30).height(30).objectFit(ImageFit.Cover)
            Text('我的名片').fontColor(Color.Black).fontSize(18)
          }.alignItems(VerticalAlign.Center).justifyContent(FlexAlign.Start)
          .alignRules({
            center: { anchor: '__container__', align: VerticalAlign.Center },
          }).margin({left:20})
          Image($r('app.media.common_arrow'))
            .width(30).height(20)
            .objectFit(ImageFit.Contain)
            .alignRules({
              center: { anchor: '__container__', align: VerticalAlign.Center },
              right: { anchor: '__container__', align: HorizontalAlign.End },
            })
        }.height(50).width('100%')
        .onClick(()=>{
          //处理点击事件
        })

        RelativeContainer(){
          Row({space:20}){
            Image($r('app.media.ic_my_face_info')).width(30).height(30).objectFit(ImageFit.Cover)
            Text('人脸信息').fontColor(Color.Black).fontSize(18)
          }.alignItems(VerticalAlign.Center).justifyContent(FlexAlign.Start)
          .alignRules({
            center: { anchor: '__container__', align: VerticalAlign.Center },
          }).margin({left:20})
          Image($r('app.media.common_arrow'))
            .width(30).height(20)
            .objectFit(ImageFit.Contain)
            .alignRules({
              center: { anchor: '__container__', align: VerticalAlign.Center },
              right: { anchor: '__container__', align: HorizontalAlign.End },
            })
        }.height(50).width('100%')
        .onClick(()=>{
          //处理点击事件
        })

        RelativeContainer(){
          Row({space:20}){
            Image($r('app.media.ic_my_domain_account')).width(30).height(30).objectFit(ImageFit.Cover)
            Text('我的订单').fontColor(Color.Black).fontSize(18)
          }.alignItems(VerticalAlign.Center).justifyContent(FlexAlign.Start)
          .alignRules({
            center: { anchor: '__container__', align: VerticalAlign.Center },
          }).margin({left:20})
          Image($r('app.media.common_arrow'))
            .width(30).height(20)
            .objectFit(ImageFit.Contain)
            .alignRules({
              center: { anchor: '__container__', align: VerticalAlign.Center },
              right: { anchor: '__container__', align: HorizontalAlign.End },
            })
        }.height(50).width('100%')
        .onClick(()=>{
          //处理点击事件
        })

        RelativeContainer(){
          Row({space:20}){
            Image($r('app.media.ic_my_archives')).width(30).height(30).objectFit(ImageFit.Cover)
            Text('我的档案').fontColor(Color.Black).fontSize(18)
          }.alignItems(VerticalAlign.Center).justifyContent(FlexAlign.Start)
          .alignRules({
            center: { anchor: '__container__', align: VerticalAlign.Center },
          }).margin({left:20})
          Image($r('app.media.common_arrow'))
            .width(30).height(20)
            .objectFit(ImageFit.Contain)
            .alignRules({
              center: { anchor: '__container__', align: VerticalAlign.Center },
              right: { anchor: '__container__', align: HorizontalAlign.End },
            })
        }.height(50).width('100%')
        .onClick(()=>{
          //处理点击事件
        })

        RelativeContainer(){
          Row({space:20}){
            Image($r('app.media.ic_settings')).width(30).height(30).objectFit(ImageFit.Cover)
            Text('设置').fontColor(Color.Black).fontSize(18)
          }.alignItems(VerticalAlign.Center).justifyContent(FlexAlign.Start)
          .alignRules({
            center: { anchor: '__container__', align: VerticalAlign.Center },
          }).margin({left:20})
          Image($r('app.media.common_arrow'))
            .width(30).height(20)
            .objectFit(ImageFit.Contain)
            .alignRules({
              center: { anchor: '__container__', align: VerticalAlign.Center },
              right: { anchor: '__container__', align: HorizontalAlign.End },
            })
        }.height(50).width('100%')
        .onClick(()=>{
          //处理点击事件
        })
      }
      .margin({left:20,right:20,top:30})
      .padding({top:10,bottom:10})
      .backgroundColor(Color.White)
      .borderRadius(10)

    }.backgroundColor('#E1F5FE')
    .width('100%')
    .height('100%')
  }
}

以上用了116行代码才实现了一个简单的5行信息的卡片,大部代码都是重复冗余的。相同属性和组件直接抽离封装,看结果:

代码语言:javascript
代码运行次数:0
运行
复制
//@Styles仅支持通用属性和通用事件
//个人信息card属性
@Styles function bgStyles () {
  .backgroundColor('#E1F5FE')
  .width('100%')
  .height('100%')
}
//个人信息card属性
@Styles function cardStyles () {
  .margin({left:20,right:20,top:30})
  .padding({top:10,bottom:10})
  .backgroundColor(Color.White)
  .borderRadius(10)
}
//@Extend支持封装指定组件的私有属性、私有事件和自身定义的全局方法
@Extend(Image) function imageStyle(){
  .width(30).height(30).objectFit(ImageFit.Cover)
}
//支持传参
@Extend(Text) function textStyle(fontSize: number){
  .fontColor(Color.Black).fontSize(fontSize)
}
@Extend(Row) function rowStyle(){
  .alignItems(VerticalAlign.Center).justifyContent(FlexAlign.Start).alignRules(AlignParentLeft).margin({left:20})
}
let AlignParentLeft: Record<string, Record<string, string | VerticalAlign | HorizontalAlign>> = {
  'center': { 'anchor': '__container__', 'align': VerticalAlign.Center },
  'left': { 'anchor': '__container__', 'align': HorizontalAlign.Start }
}
let AlignParentRight: Record<string, Record<string, string | VerticalAlign | HorizontalAlign>> = {
  'center': { 'anchor': '__container__', 'align': VerticalAlign.Center },
  'right': { 'anchor': '__container__', 'align': HorizontalAlign.End }
}
@Entry
@ComponentV2
struct test4{
  @Builder
  buildItem(imgS:ResourceStr,itemName:string,onClick: () => void){
    RelativeContainer(){
      Row({space:20}){
        Image(imgS).imageStyle()
        Text(itemName).textStyle(18)
      }.rowStyle()
      Image($r('app.media.common_arrow')).imageStyle().alignRules(AlignParentRight)
    }.height(50).width('100%')
    .onClick(onClick)
  }
  build() {
    Column(){
      Column(){
        this.buildItem($r('app.media.ic_my_card'),'我的名片',()=>{
            showToast('我的名片')
        })
        this.buildItem($r('app.media.ic_my_face_info'),'人脸信息',()=>{
          showToast('人脸信息')
        })
        this.buildItem($r('app.media.ic_my_domain_account'),'我的订单',()=>{
          showToast('我的订单')
        })
        this.buildItem($r('app.media.ic_my_archives'),'我的档案',()=>{
          showToast('我的档案')
        })
        this.buildItem($r('app.media.ic_settings'),'设置',()=>{
          showToast('设置')
        })
      }
      .cardStyles()
    }.bgStyles()
  }
}

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 封装!封装!封装!
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档