HarmonyOS ArkTS 组件复用指南:深入理解 @Reusable 装饰器(详尽版)

60 阅读5分钟

HarmonyOS ArkTS 组件复用指南:深入理解 @Reusable 装饰器(详尽版)

一起来构建生态吧~

在 ArkTS/ArkUI 里构建组件化应用时,我们一方面追求 组件拆分清晰、逻辑稳定;另一方面也要关注 性能和运行效率。 当大量相同结构的组件不停创建和销毁时,例如列表长滚动、动态布局切换等,性能瓶颈很可能就在这里

为了减少重复创建导致的开销,HarmonyOS 提供了一个非常实用的机制: @Reusable 装饰器 —— 标记自定义组件支持复用,从而提升渲染性能。 华为开发者官网


1. 为什么要关注组件复用?

在传统 UI 渲染体系中,当一个组件被移除(比如列表滑出屏幕)后:

  • 组件实例被销毁
  • UI 的创建和销毁都要开销一笔资源
  • 滑动等高频操作会产生大量重复创建/销毁

这会导致:

  • UI 卡顿感明显
  • 内存和渲染压力增大
  • 帧率波动甚至掉帧

@Reusable 的核心目的就是:

标记某个组件可以被复用缓存起来,而不是每次都重新创建和销毁,从而降低渲染成本和提升体验流畅性。 华为开发者官网


2. @Reusable 到底是什么?

简要定义:

@Reusable 是一个装饰器,用于标记任意自定义组件,使其支持复用机制。应用此标记的组件,在被从组件树移除时,其实例和对应的底层视图对象会被缓存起来,随后再次需要此组件时会从缓存中重用。 华为开发者官网

也就是说:

  • 它只作用于 自定义组件,不能用于原生基础组件
  • 标记后组件在卸载/重建时能进入复用流程
  • 可以显著提升渲染性能、降低重复创建代价

3. 官方核心机制解析

使用场景主要集中在 动态创建和销毁组件频繁的地方,例如:

列表滑动

  • Items 滑入屏幕创建
  • 滑出屏幕销毁
  • 用复用机制缓存旧实例

条件渲染

根据条件判断插入/删除某类组件

使用 @Reusable 后:

  1. 当组件从组件树移除时,生命周期不完全销毁 而是放入 复用缓存池
  2. 下次再次需要创建相同组件时 优先从缓存池拿出旧实例,而不是新建对象
  3. 节省内存分配、JSView 重建、布局/渲染计算等开销 nutpi.net

4. 使用前提与限制

你在使用时要注意这些“工程边界”,否则容易踩坑:

1. 只能标记自定义组件

@Reusable 必须和 @Component 结合使用,不能修饰基础组件。本质上它是告诉框架“这个自定义组件可以进入复用机制”。 CSDN

2. 不支持和 @Builder 混用

@Builder 是轻量级构造器,不支持复用机制,所以如果同时标记会报错。 阿里云开发者社区

3. 嵌套复用需要谨慎

不建议在父子组件都进行嵌套 @Reusable 标记,否则会出现多层缓存导致管理混乱。 阿里云开发者社区


5. 基本使用示例(一步步讲明白)

下面我们从最简单的例子一步一步开始:


5.1 定义一个可复用组件

假设我们有一个列表项组件 ListItem

 @Reusable
 @Component
 export struct ListItem {
   @State name: string
 ​
   build() {
     Column() {
       Text(this.name)
         .fontSize(16)
         .fontColor('#333')
         .padding({ left: 12, top: 8, bottom: 8 })
     }
   }
 }

这里发生了几件事:

  • @Component 标记了一个自定义组件
  • @Reusable 表示它支持复用机制

5.2 在父组件中使用

父组件里可以像正常那样使用:

 @Entry
 @Component
 export struct MyList {
   @State items: string[] = ['ONE', 'TWO', 'THREE']
 ​
   build() {
     Column() {
       ForEach(this.items, (item, index) => {
         ListItem({ name: item })
           .reuseId('ListItem')  // 标识该组件复用分组
       })
     }
   }
 }

这里的 .reuseId('ListItem') 用来标识复用的“类别”。 同一类别的复用池会共享缓存。 nutpi.net


6. 生命周期钩子:怎么处理复用前/复用后逻辑

为了应对状态传递或参数注入,你可以使用生命周期回调:

aboutToReuse(params)`

这个回调会在组件从复用池重新拿出来加入组件树前触发,你可以:

  • 把新的构造参数赋值给组件状态
  • 做初始化
 aboutToReuse(params: { [key: string]: unknown }) {
   // 把上次复用的实例数据替换成最新数据
   this.name = params.name as string
 }

7. 典型应用场景(真实项目中绝对用得上)

长列表高性能渲染

例如滚动列表里不断创建/销毁会导致性能下降,尤其是移动端弱设备。

如果列表项使用了 @Reusable,不会频繁分配和销毁对象,滚动更平滑。


动态条件渲染

当你在不同数据条件下来回切换某个组件时:

没有复用: 组件生命周期一直新建 → 销毁 有复用: 组件实例复用,避免重复开销


8. “像人写的总结话”

对于 UI 性能优化来说,一个常见的痛点是 组件创建销毁频率过高带来的卡顿。 相比于单纯的 UI 逻辑组织,组件复用策略能真正从性能层面提升流畅度。 @Reusable 装饰器正是 ArkUI 官方提供的“复用解决方案”,它很自然地融合到 ArkTS 组件体系里,让你用声明式写法开发时不必牺牲性能。 华为开发者官网


9. 最佳实践建议

总结成一个清单,方便读者在项目里直接拿去用:

建议 1:尽量给列表项用上 @Reusable

比如设置页、歌词列表、聊天记录、商品列表等都能受益。

建议 2:为不同复用组件指定不同 reuseId

即使是同一个组件结构,但复用标识不同会让它们分到不同缓存池,避免意外数据混乱。

建议 3:在 aboutToReuse 里处理参数更新

避免复用旧状态遗留到新生成的组件实例。

建议 4:不要过度复用小组件

对于极简单不会频繁创建/销毁的组件,不用 @Reusable 也没问题。


最终总结

主题核心价值
@Reusable 是什么让自定义组件支持复用机制
优点减少重复创建/销毁,提升性能
适用场景列表、动态组件、切换视图等
关键参数reuseId + 生命周期函数
最主要收益流畅的渲染体验 + 低内存开销