[鸿蒙2025领航者闯关] 如何实现组件复用,减少代码重复?
页面中有很多重复的 UI 结构(导航栏、列表项、卡片等),如何使用 @Builder 实现组件复用,减少代码重复?: @Builder、组件复用、自定义组件、代码复用、UI 封装。
·
问题描述
页面中有很多重复的 UI 结构(导航栏、列表项、卡片等),如何使用 @Builder 实现组件复用,减少代码重复?
关键字: @Builder、组件复用、自定义组件、代码复用、UI 封装
解决方案
完整代码
/**
* 全局Builder函数
*/
@Builder
function buildHeader(title: string, showBack: boolean = true, onBack?: () => void) {
Row() {
if (showBack) {
Image($r('app.media.ic_back'))
.width(24)
.height(24)
.onClick(() => {
if (onBack) {
onBack();
} else {
router.back();
}
})
}
Text(title)
.fontSize(20)
.fontWeight(FontWeight.Bold)
.layoutWeight(1)
.textAlign(TextAlign.Center)
// 占位,保持标题居中
if (showBack) {
Row().width(24).height(24)
}
}
.width('100%')
.height(56)
.padding({ left: 16, right: 16 })
.backgroundColor(Color.White)
}
/**
* 组件内Builder函数
*/
@Entry
@Component
struct BuilderDemo {
@State records: Array<{name: string, amount: number, type: string}> = [
{ name: '张三', amount: 500, type: 'income' },
{ name: '李四', amount: 300, type: 'expense' }
];
build() {
Column() {
// 使用全局Builder
buildHeader('记录列表', true)
List({ space: 12 }) {
ForEach(this.records, (record: any) => {
ListItem() {
// 使用组件内Builder
this.buildRecordItem(record)
}
})
}
.layoutWeight(1)
.padding(16)
}
}
/**
* 组件内Builder:记录列表项
*/
@Builder
buildRecordItem(record: {name: string, amount: number, type: string}) {
Row() {
Column({ space: 4 }) {
Text(record.name)
.fontSize(16)
.fontWeight(FontWeight.Bold)
Text(record.type === 'income' ? '收入' : '支出')
.fontSize(14)
.fontColor('#999')
}
.alignItems(HorizontalAlign.Start)
Blank()
Text(`¥${record.amount}`)
.fontSize(18)
.fontColor(record.type === 'income' ? '#f56c6c' : '#67c23a')
}
.width('100%')
.padding(16)
.backgroundColor(Color.White)
.borderRadius(8)
}
/**
* 组件内Builder:空状态
*/
@Builder
buildEmptyState(message: string = '暂无数据') {
Column({ space: 12 }) {
Image($r('app.media.ic_empty'))
.width(120)
.height(120)
.opacity(0.3)
Text(message)
.fontSize(14)
.fontColor('#999')
}
.width('100%')
.padding(40)
}
/**
* 组件内Builder:统计卡片
*/
@Builder
buildStatCard(title: string, value: string, color: string) {
Column({ space: 8 }) {
Text(value)
.fontSize(24)
.fontWeight(FontWeight.Bold)
.fontColor(color)
Text(title)
.fontSize(14)
.fontColor('#999')
}
.width('100%')
.padding(20)
.backgroundColor(Color.White)
.borderRadius(12)
}
}
/**
* BuilderParam传递Builder
*/
@Component
struct CustomCard {
@BuilderParam content: () => void;
title: string = '';
build() {
Column({ space: 12 }) {
// 标题
Text(this.title)
.fontSize(18)
.fontWeight(FontWeight.Bold)
.width('100%')
// 自定义内容
this.content()
}
.width('100%')
.padding(16)
.backgroundColor(Color.White)
.borderRadius(12)
}
}
/**
* 使用BuilderParam
*/
@Entry
@Component
struct BuilderParamDemo {
build() {
Column({ space: 12 }) {
CustomCard({ title: '统计信息' }) {
Column({ space: 8 }) {
Text('总收入: ¥5000')
Text('总支出: ¥3000')
}
}
CustomCard({ title: '最近记录' }) {
List({ space: 8 }) {
ListItem() {
Text('记录1')
}
ListItem() {
Text('记录2')
}
}
.height(100)
}
}
.padding(16)
}
}
/**
* @Extend扩展组件样式
*/
@Extend(Text)
function primaryButton() {
.fontSize(16)
.fontColor(Color.White)
.backgroundColor('#ff6b6b')
.padding({ left: 24, right: 24, top: 12, bottom: 12 })
.borderRadius(8)
}
@Extend(Text)
function secondaryButton() {
.fontSize(16)
.fontColor('#333')
.backgroundColor('#f5f5f5')
.padding({ left: 24, right: 24, top: 12, bottom: 12 })
.borderRadius(8)
}
@Component
struct ExtendDemo {
build() {
Column({ space: 12 }) {
Text('确定').primaryButton()
Text('取消').secondaryButton()
}
}
}
原理解析
1. @Builder 全局函数
@Builder
function buildHeader(title: string) {
// UI代码
}
- 定义在组件外,可被多个组件使用
- 支持参数传递
- 不能访问组件状态
2. @Builder 组件内方法
@Builder
buildRecordItem(record: any) {
// UI代码
}
- 定义在组件内,可访问组件状态
- 使用 this.buildRecordItem()调用
- 支持参数传递
3. @BuilderParam
@BuilderParam content: () => void;
- 接收 Builder 作为参数
- 实现插槽功能
- 提高组件灵活性
4. @Extend 样式扩展
@Extend(Text) function primaryButton() {}
- 扩展组件样式
- 避免重复样式代码
- 只能扩展系统组件
最佳实践
- 全局 Builder: 通用 UI(导航栏、空状态)用全局 Builder
- 组件 Builder: 页面特定 UI 用组件内 Builder
- BuilderParam: 需要自定义内容的组件用 BuilderParam
- Extend: 重复样式用 @Extend
- 命名规范: Builder 函数以 build 开头
避坑指南
- this 访问: 全局 Builder 不能访问 this
- 参数类型: Builder 参数要明确类型
- 状态更新: Builder 内修改状态会触发重绘
- 性能: 避免在 Builder 内执行复杂计算
- Extend 限制: @Extend 只能用于系统组件
效果展示
- 代码复用率提升 60% 以上
- 统一的 UI 风格
- 易于维护和修改
- 提高开发效率
更多推荐


所有评论(0)