本文同步发表于我的微信公众号,微信搜索 程语新视界 即可关注,每个工作日都有文章更新
鸿蒙(HarmonyOS)的ArkUI框架中,@Reusable 是一个用于组件复用优化的装饰器,通过减少重复创建相同组件的开销来提升性能。以下是其核心作用、使用方法和示例:
一、@Reusable 的作用
- 组件复用
- 标记为
@Reusable的组件会被框架缓存,当相同类型的组件需要重新渲染时,优先复用已创建的实例,而非重新构建。
- 标记为
- 性能提升
- 减少内存分配和初始化开销,尤其适用于频繁渲染的列表项或动态生成的组件。
- 智能回收
- 当组件长时间未使用时,框架会自动释放其缓存,避免内存泄漏。
二、方法 aboutToReuse() 的作用
- 复用时的初始化
- 当
@Reusable组件被框架从缓存池中取出复用时(而非首次创建),会触发此方法。
- 当
- 与
aboutToAppear()的区别aboutToAppear():组件首次创建或重新创建时调用。aboutToReuse():组件被复用时调用(优先于build())。
三、使用场景
| 场景 | 是否推荐使用 | 原因 |
|---|---|---|
| 列表项(List/Grid) | ✅ 强烈推荐 | 避免滚动时重复创建相同组件 |
| 动态条件渲染组件 | ✅ 推荐 | 组件频繁显示/隐藏时复用 |
| 静态布局组件 | ❌ 不推荐 | 无复用需求,反而增加框架管理开销 |
| 场景 | 是否需要 aboutToReuse() | 原因 |
|---|---|---|
| 列表项(List/Grid)滚动 | ✅ 必用 | 复用组件时需要重置状态或更新数据 |
| 动态条件渲染组件 | ✅ 推荐 | 组件重新显示时可能需要恢复上下文 |
| 静态布局 | ❌ 无需 | 无复用需求 |
四、使用示例
1. 基本用法:标记可复用组件
@Reusable
@Component
struct ReusableCard {
@State private clickCount: number = 0; // 组件内部状态
@Prop title: string; // 父组件传递的数据
aboutToReuse(params?: Record<string, Object>) {
console.log('组件被复用,参数:', params);
this.clickCount = 0; // 重置点击计数
}
build() {
Column() {
Text(`${this.title} (点击次数: ${this.clickCount})`)
Button('点击')
.onClick(() => this.clickCount++)
}
}
}
2. 在列表(List)中复用组件
@Entry
@Component
struct ReusableListExample {
@State data: string[] = ['Item 1', 'Item 2', 'Item 3'];
build() {
List() {
ForEach(this.data, (item: string) => {
ListItem() {
ReusableCard({ title: item }) // 复用ReusableCard组件
}
}, (item: string) => item)
}
.onClick(() => {
this.data.push(`Item ${this.data.length + 1}`); // 动态添加数据
})
}
}
3. 动态更新复用参数
aboutToReuse(params?: Record<string, Object>) {
if (params?.newTitle) {
this.title = params.newTitle; // 更新父组件传递的Prop
}
}
// 父组件调用时传递参数
ReusableCard({ title: '初始标题' })
.onClick(() => {
this.cardParams = { newTitle: '更新后的标题' };
})
4. 动态条件渲染中的复用
@Entry
@Component
struct ToggleExample {
@State showCard: boolean = false;
build() {
Column() {
Button('切换显示')
.onClick(() => this.showCard = !this.showCard)
if (this.showCard) {
ReusableCard({ title: '动态显示的卡片' }) // 复用已缓存的组件
}
}
}
}
五、执行流程与生命周期顺序

- 首次创建:
aboutToAppear()→build() - 复用实例:
aboutToReuse()→build()
六、实现原理
- 缓存机制
- 当
@Reusable组件首次渲染时,框架会将其实例存入缓存池。
- 当
- 复用条件
- 当满足以下条件时,优先从缓存池获取组件实例:
- 组件类型相同(如
ReusableCard)。 - 关键属性(如
@Prop、@Link)的值未变化。
- 组件类型相同(如
- 当满足以下条件时,优先从缓存池获取组件实例:
- 生命周期
- 复用时不会触发
aboutToAppear,但会触发build()。
- 复用时不会触发
七、注意事项
- 状态隔离
- 复用时组件的
@State和@Link会被重置,需通过@Prop或@Provide传递数据。
- 复用时组件的
- 避免副作用
- 不要在
build()中执行网络请求等副作用操作,可能因复用导致重复调用。
- 不要在
- 合理使用
- 对简单组件(如纯文本)使用
@Reusable可能反而降低性能(框架管理开销 > 复用收益)。
- 对简单组件(如纯文本)使用
- 参数传递
aboutToReuse()的params参数需通过父组件动态更新(如修改@Prop或调用方法)。
八、完整示例
@Reusable
@Component
struct UserCard {
@Prop userId: number;
@State private userData: { name?: string } = {};
aboutToReuse() {
this.loadUserData(); // 复用后重新加载数据
}
loadUserData() {
// 模拟API请求
setTimeout(() => {
this.userData = { name: `User_${this.userId}` };
}, 100);
}
build() {
Column() {
if (this.userData.name) {
Text(this.userData.name).fontSize(18)
} else {
LoadingProgress() // 数据加载中显示Loading
}
}
.onClick(() => this.loadUserData())
}
}
@Entry
@Component
struct UserList {
@State users: number[] = [1, 2, 3];
build() {
List() {
ForEach(this.users, (id: number) => {
ListItem() {
UserCard({ userId: id })
}
}, (id: number) => id.toString())
}
}
}
4820

被折叠的 条评论
为什么被折叠?



