写点什么

鸿蒙 Next 组件样式封装

作者:auhgnixgnahz
  • 2025-06-23
    北京
  • 本文字数:3692 字

    阅读完需:约 12 分钟

封装!封装!封装!

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


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



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


@Entry@ComponentV2struct 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 行信息的卡片,大部代码都是重复冗余的。相同属性和组件直接抽离封装,看结果:


//@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@ComponentV2struct 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()  }}</string, record<string, string | verticalalign | horizontalalign></string, record<string, string | verticalalign | horizontalalign>
复制代码


这样用很少代码就实现了相同的样式,如果再增加相同信息,只需要一两行代码即可实现,如果修改布局只需要修改一处就可以全局修改!


发布于: 刚刚阅读数: 2
用户头像

auhgnixgnahz

关注

还未添加个人签名 2018-07-10 加入

还未添加个人简介

评论

发布
暂无评论
鸿蒙Next 组件样式封装_鸿蒙Next_auhgnixgnahz_InfoQ写作社区