HarmonyOS应用开发实战(基础篇)Day11 -《组件复用》
在鸿蒙应用开发过程中,随着项目规模扩大,页面逻辑和 UI 结构会变得日益复杂。若将所有代码写在单一组件中,不仅会导致可读性下降,还会造成**重复代码泛滥**,严重违背“DRY(Don’t Repeat Yourself)”原则。

组件复用
在鸿蒙应用开发过程中,随着项目规模扩大,页面逻辑和 UI 结构会变得日益复杂。若将所有代码写在单一组件中,不仅会导致可读性下降,还会造成重复代码泛滥,严重违背“DRY(Don’t Repeat Yourself)”原则。
因此,组件复用成为提升开发效率、保障代码一致性、降低维护成本的关键手段。通过将通用 UI 片段(如用户卡片、商品项、消息气泡等)抽取为独立单元,我们可以在多个页面或列表中无缝复用,实现“一次编写,多处使用”。
正如你在开发中可能遇到的困惑:“这个 UI 片段散落在多个地方,修改起来太麻烦”——这正是组件化要解决的核心问题。
🎯 复用目标:
- 提高代码可维护性
- 减少冗余逻辑
- 支持团队协作(UI 与逻辑解耦)
- 便于单元测试

在 ArkTS 中,官方提供了两种主流的组件复用方式:
- 抽取为独立组件文件(使用
@Component+@Prop) - 定义为自定义构建器(使用
@Builder)
下面我们将分别详解这两种方式的实现细节、适用场景与注意事项。
提取到文件夹中(独立组件)
这是最常用、最推荐的组件复用方式,尤其适用于跨页面、跨模块的 UI 单元。其核心思想是:将一段 UI 逻辑封装成一个可接收外部数据的独立组件,并通过 @Prop 装饰器实现单向数据流(父 → 子)。
实现步骤
- 在项目目录下创建专门的组件文件夹(如
components或ui); - 新建
.ets文件(如UserList.ets); - 使用
@Component声明组件,并通过@Prop接收外部传入的数据; - 在需要使用的地方导入并调用该组件。
// src/main/ets/components/UserList.ets
import { User } from "../common/UserDemo"
@Component
export struct UserList {
@Prop item: User; // 接收父组件传入的用户对象
build() {
Column() {
Text('姓名:' + this.item.name)
.fontSize(16)
.fontWeight(FontWeight.Bold)
Text('邮箱:' + this.item.email)
.fontSize(14)
.fontColor('#666')
}
.width('100%')
.padding(10)
.backgroundColor('#f9f9f9')
.borderRadius(8)
}
}
💡 关键点解析:
@Prop:表示该属性由父组件传入,子组件不可修改(单向绑定),确保数据流清晰;export struct:必须导出,才能被其他文件导入;- 路径规范:建议将组件集中管理,如
src/main/ets/components/,便于查找与维护。

使用方式
在父组件中导入 UserList,并通过大括号 {} 传递参数(这是 ArkTS 的语法要求):
// 在 Index.ets 中使用
import { UserList } from '../components/UserList'
// ...
ForEach(this.users, (item: User) => {
UserList({ item: item }) // 注意:必须用 { } 包裹参数
})
⚠️ 常见错误:
若写成UserList(item)(无大括号),编译器会报错,因为 ArkTS 要求具名参数必须显式声明。

优势与适用场景
- ✅ 高内聚低耦合:组件内部逻辑封闭,仅通过
@Prop暴露接口; - ✅ 支持 TypeScript 类型检查:传参时自动校验类型;
- ✅ 可跨页面复用:如用户卡片既可用于“联系人列表”,也可用于“聊天详情”;
- ✅ 便于样式统一:修改
UserList.ets即可全局生效。
Builder(自定义构建器)
@Builder 是 ArkTS 提供的一种轻量级 UI 复用机制,适用于同一组件内部的 UI 片段提取。它本质上是一个带参数的函数,返回一段 UI 描述,不创建新的组件实例,性能开销极低。
实现方式
在当前组件内部定义 @Builder 方法:
// 在 Index.ets 内部
@Builder
musicBuildList(item: User) {
Column() {
Text('姓名:' + item.name)
.fontSize(16)
Text('邮箱:' + item.email)
.fontSize(14)
}
.width('100%')
.padding(10)
.margin(5)
}
使用方式
直接在 build() 中调用,无需导入:
ForEach(this.users, (item: User) => {
this.musicBuildList(item) // 直接调用,像函数一样
})

优势与局限
| 优势 | 局限 |
|---|---|
| ✅ 语法简洁,无额外文件 | ❌ 仅限当前组件内部使用 |
| ✅ 零性能开销(无组件实例化) | ❌ 无法跨页面复用 |
| ✅ 适合简单、高频的 UI 片段 | ❌ 不支持 @State、@Prop 等状态管理 |
📌 使用建议:
- 若某段 UI 仅在一个页面内重复出现(如列表项、表单项),优先使用
@Builder;- 若需跨页面共享,或包含复杂交互逻辑(如点击事件、状态变化),则应使用独立组件。
两种方式对比总结
| 特性 | 独立组件(@Component + @Prop) |
自定义构建器(@Builder) |
|---|---|---|
| 作用域 | 全局(可跨页面) | 仅当前组件内部 |
| 数据传递 | 通过 @Prop(单向) |
函数参数(值传递) |
| 状态管理 | 支持 @State, @Link 等 |
不支持 |
| 性能开销 | 有组件实例化成本 | 几乎为零 |
| 适用场景 | 通用 UI 单元(卡片、按钮、弹窗) | 页面内重复 UI 片段 |
| 工程结构 | 需新建文件,目录清晰 | 代码内联,快速实现 |
最佳实践建议
-
命名规范:
- 独立组件:
PascalCase(如UserCard.ets) - Builder:
camelCase(如renderUserItem)
- 独立组件:
-
目录组织:
src/main/ets/ ├── components/ # 通用组件 │ ├── UserCard.ets │ └── ProductItem.ets ├── pages/ # 页面组件 └── common/ # 工具类、模型 -
避免过度拆分:
若某 UI 片段仅使用一次,无需强行抽取,保持代码简洁性更重要。 -
类型安全:
无论哪种方式,都应为参数添加 TypeScript 类型注解,如item: User。
通过合理运用 独立组件 与 自定义构建器,开发者可以构建出高内聚、低耦合、易维护的鸿蒙应用架构,大幅提升开发效率与代码质量。
更多推荐


所有评论(0)