大家好,我是潘Sir,持续分享IT技术,帮你少走弯路。《鸿蒙应用开发从入门到项目实战》系列文章持续更新中,陆续更新AI+编程、企业级项目实战等原创内容、欢迎关注!
上一篇文章讲解了ArkUI中样式复用思想,本节继续使用自定义组件对商品列表进行优化。
复习知识内容:
- 创建自定义组件
- @Builder
- @Styles
在原来pages/layout/ProductList.ets基础上进行优化

一、自定义组件优化头部
实际项目开发中,存在多个界面共享顶部的情况。因此把顶部抽取出来作为自定义组件共用。

1.1 静态头部制作
拷贝ic_public_back.png和ic_public_refresh.png到resources/base/media目录
拷贝pages/layout/list/ProductList.ets文件,重命名为ProductListLast.ets
(直接复制的文件,不会再resources/base/profile/main_pages.json文件中配置路由,需要手动设置:"pages/layout/list/ProductListLast",)
修改标题部分:
// 标题 Row() { Image($r('app.media.ic_public_back')) .width(30) Text('商品列表') .fontSize(30) .fontWeight(FontWeight.Bold) Blank() Image($r('app.media.ic_public_refresh')) .width(30) } .width('100%') // .height(30) //控制高度 .margin({ bottom: 20 })
效果

1.2 头部抽取为组件
1.2.1 抽取到同一个文件中
// 自定义顶部组件 @Component struct Header { private title: ResourceStr build() { // 标题 Row() { Image($r('app.media.ic_public_back')) .width(30) Text(this.title) //从外层传入 .fontSize(30) .fontWeight(FontWeight.Bold) Blank() Image($r('app.media.ic_public_refresh')) .width(30) } .width('100%') // .height(30) //控制高度 // .margin({ bottom: 20 }) //放到外层控制 } }
原来头部的内容替换为自定义组件使用
// 使用自定义组件 Header({ title: '商品列表' }) .margin({bottom:20})
效果和原来一致。
1.2.2 单独抽取为一个文件
在pages/component目录新建common目录,新建ArkTS File,名称为:CommonComponents.ets,并将自定义顶部组件代码粘贴进去,并通过export将组件导出。
// 自定义顶部组件 @Component export struct Header { private title: ResourceStr build() { // 标题 Row() { Image($r('app.media.ic_public_back')) .width(30) Text(this.title) //从外层传入 .fontSize(30) .fontWeight(FontWeight.Bold) Blank() Image($r('app.media.ic_public_refresh')) .width(30) } .width('100%') // .height(30) //控制高度 // .margin({ bottom: 20 }) //放到外层控制 } }
回到ProductListLast.ets文件,导入自定义组件
// 导入自定义顶部组件 import {Header} from '../../component/common/CommonComponents'
二、自定义构建函数优化UI结构
以上代码中,可读性较差,可以把商品列表的部分封装起来,自定义组件或自定义构建函数都可以优化。
2.1 全局自定义构建函数
通过@Builder自定义构建函数,将商品卡片信息放置到函数中,函数定义在全局
// 全局自定义构建函数 @Builder function ItemCard(item:Item2){ Row({ space: 10 }) { Image(item.image) .width(100) Column({ space: 4 }) { if (item.discount) { Text(item.name) .fontSize(20) .fontWeight(FontWeight.Bold) Text('原价:¥' + item.price) .fontColor('#CCC') .fontSize(14) .decoration({ type: TextDecorationType.LineThrough }) Text('折扣价:¥' + (item.price - item.discount)) .fontColor('#F36') .fontSize(18) Text('补贴:¥' + item.discount) .fontColor('#F36') .fontSize(18) } else { Text(item.name) .fontSize(20) .fontWeight(FontWeight.Bold) Text('¥' + item.price) .fontColor('#F36') .fontSize(18) } } .height('100%') .alignItems(HorizontalAlign.Start) } .width('100%') .backgroundColor('#FFF') .borderRadius(20) .height(120) .padding(10) }
将原有线上组件的地方替换为函数调用
ItemCard(item)
这样,界面效果不变,但是代码更简洁,可读性更高。
2.2 局部自定义构建函数
函数定义在组件内部,将以上组件代码拷贝,并去掉function关键字
// 局部自定义构建函数 不要function关键字 @Builder ItemCard(item:Item2){ Row({ space: 10 }) { Image(item.image) .width(100) Column({ space: 4 }) { if (item.discount) { Text(item.name) .fontSize(20) .fontWeight(FontWeight.Bold) Text('原价:¥' + item.price) .fontColor('#CCC') .fontSize(14) .decoration({ type: TextDecorationType.LineThrough }) Text('折扣价:¥' + (item.price - item.discount)) .fontColor('#F36') .fontSize(18) Text('补贴:¥' + item.discount) .fontColor('#F36') .fontSize(18) } else { Text(item.name) .fontSize(20) .fontWeight(FontWeight.Bold) Text('¥' + item.price) .fontColor('#F36') .fontSize(18) } } .height('100%') .alignItems(HorizontalAlign.Start) } .width('100%') .backgroundColor('#FFF') .borderRadius(20) .height(120) .padding(10) }
在原来商品列表处进行调用,条用局部自定义组件,需要使用this关键字
this.ItemCard(item) //局部组件使用
三、自定义样式装饰器优化样式
3.1 容器全局样式
将Column的通用样式抽取到自定义样式函数fillScreen中
将fillScreen放到组件外
// 自定义全局公共样式 @Styles function fillScreen(){ .width('100%') .height('100%') .backgroundColor('#EFEFEF') .padding(20) }
使用
Column({ space: 8 }) {...} // 自定义样式 .fillScreen()
3.2 容器局部样式
将fillScreen放到组件内,去掉function关键字
// 自定义局部公共样式 @Styles fillScreen(){ .width('100%') .height('100%') .backgroundColor('#EFEFEF') .padding(20) }
使用方式不变,抽取后预览效果一致。
3.3 商品信息样式抽取
将商品信息样式中的价格样式抽取到公共全局样式中,由于fontColor和fontSize是Text专有的,不是公共样式,因此使用@Styles会报错,应该使用Extend(Text),并且Textend只能写在全局。
// 自定义全局价格样式 // @Styles function priceText(){ @Extend(Text) function priceText(){ //Extend继承模式不能写在组件内,只能写在全局 .fontColor('#F36') .fontSize(18) }
将原来的样式方法改为自定义方法即可
// .fontColor('#F36') // .fontSize(18) .priceText()
这样,不仅代码层次更清晰,还可以更方便的维护和修改,只需要修改公共样式,其它引用的地方就可以直接被修改。
《鸿蒙应用开发从入门到项目实战》系列文章持续更新中,陆续更新AI+编程、企业级项目实战等原创内容,防止迷路,欢迎关注!