HarmonyOS 组件复用 @Reusable 装饰器的基本使用

HarmonyOS 组件复用 @Reusable 装饰器的基本使用

作用

@Reusable装饰器标记的自定义组件支持视图节点、组件实例和状态上下文的复用,避免重复创建和销毁,提升性能。

原理

使用@Reusable装饰器时,表示该自定义组件可以复用。与@Component结合使用,标记为@Reusable的自定义组件在从组件树

中移除时,组件及其对应的 JS 对象将被放入复用缓存中。后续创建新自定义组件节点时,将复用缓存中的节点,从而节约组件重新

创建的时间。

  1. 标记了@Reusable的自定义组件listItem列表项,在滑动出屏幕一定范围后,从组件树上被移除,组件的对象实例被放入 CustomNode 虚拟结点(与自定义组件一一对应的自定义结点)。
  2. 在不断滑动过程中,列表的RecycleManager将这些CustomNode虚拟结点回收,根据复用标识reuseId分组,形成CachedRecycleNodes的集合,即视图对象的复用缓存池。
  3. 继续滑动,新的listItem需要在列表上显示时,RecycleManager优先从复用缓存池(CachedRecycleNodes集合)中查找对应reuseId的视图对象,然后将新的数据绑定到该视图,重用该节点并添加到组件树上。

适用场景

常见的组件复用开发场景是长列表滑动:在应用展示大量数据的列表界面中,当用户快速地进行滑动操作,列表项反复创建销毁可能导致卡顿等性能问题。这种情况下,使用组件复用机制可以重用已经创建过的列表项视图,提高滑动的流畅度。

基本使用

对于要复用的组件核心是要使用 @Reusable 装饰器 和 reuseId

  • @Reusable 用来定义可复用的组件
  • reuseId 表示该组件属于哪一类,因为可以可以复用好很多不同的组件

定义要复用的组件 Child

typescript 复制代码
@Component
struct Child {
  @State message: string = 'child';

  build() {
    Column() {
      Text(this.message)
        .fontSize(30)
    }
    .borderWidth(1)
    .height(100)
  }
}

组件添加上复用装饰器 @Reusable

typescript 复制代码
@Reusable
@Component
struct Child {
// ...
}

父组件使用

typescript 复制代码
@Entry
@Component
struct Index {
  build() {
    Column() {
      // 如果只有一个复用的组件,可以不用设置reuseId。
      Child()
        .reuseId('Child')
    }
  }
}

效果

子组件属性更新

很多时候,我们要复用的自己,往往是伴随着属性更新的,比如长列表中的联系人列表,结构可能一样,但是内容是不一样。

要实现复用在组件更新,需要搭配组件的声明周期 aboutToReuse

这里模拟长列表中反复切换显示子组件

当一个可复用的自定义组件从复用缓存中重新加入到节点树时,触发 aboutToReuse 生命周期回调,并将组件的构造参数传递

给 aboutToReuse。

父组件控制子组件的显示和属性变更

typescript 复制代码
@Entry
@Component
struct Index {
  @State
  num: number = 1
  @State
  isShow: boolean = false

  build() {
    Column() {
      Button("+")
        .onClick(() => {
          this.isShow = !this.isShow
        })
      if (this.isShow) {
        // 如果只有一个复用的组件,可以不用设置reuseId。
        Child({ message: 'child' + ++this.num })
          .reuseId('Child')
      }
    }
  }
}

子组件使用 aboutToReuse 生命周期 更新属性

params 表示接收父组件传递的属性,对应父组件传递给子组件的 { message: 'child' + ++this.num }

typescript 复制代码
  aboutToReuse(params: Record<string, string>) {
    this.message = params.message
  }

效果

限制条件

  1. @Reusable 装饰器仅用于自定义组件。
  2. ComponentContent 不支持传入@Reusable 装饰器装饰的自定义组件。
  3. @Reusable 装饰器不建议嵌套使用,会增加内存,降低复用效率,加大维护难度。
  4. 避免对@Link/@ObjectLink/@Prop 等自动更新的状态变量,在 aboutToReuse 中重复更新。最佳实践请参考组件复用最佳实践-优化状态管理,精准控制组件刷新范围使用
  5. 在滑动场景中,使用组件复用通常需要用该回调函数去更新组件的状态变量,因此在该回调函数中应避免耗时操作,否则会导致丢帧卡顿。最佳实践请参考主线程耗时操作优化指导-组件复用回调

其他搭配场景

链接

关于我们

关于青蓝逐码组织

如果你兴趣想要了解更多的鸿蒙应用开发细节和最新资讯甚至你想要做出一款属于自己的应用!欢迎在评论区留言或者私信或者看我个人信息,可以加入技术交流群。

相关推荐
im_AMBER21 分钟前
React 17
前端·javascript·笔记·学习·react.js·前端框架
大师兄66681 小时前
鸿蒙 ArkTS 入门教程:小白实战 List 列表开发(详解 @State, ForEach, @Builder)
list·harmonyos·arkts·builder·foreach·state·鸿蒙入门
谷歌开发者1 小时前
Web 开发指向标 | Chrome 开发者工具学习资源 (六)
前端·chrome·学习
一晌小贪欢1 小时前
【Html模板】电商运营可视化大屏模板 Excel存储 + 一键导出(已上线-可预览)
前端·数据分析·html·excel·数据看板·电商大屏·大屏看板
发现你走远了1 小时前
连接模拟器网页进行h5的调试(使用Chrome远程调试(推荐)) 保姆级图文
前端·chrome
街尾杂货店&3 小时前
css - 实现三角形 div 容器,用css画一个三角形(提供示例源码)简单粗暴几行代码搞定!
前端·css
顺凡3 小时前
删一个却少俩:Antd Tag 多节点同时消失的原因
前端·javascript·面试
小白路过3 小时前
CSS transform矩阵变换全面解析
前端·css·矩阵
爬山算法3 小时前
Redis(110)Redis的发布订阅机制如何使用?
前端·redis·bootstrap
REDcker3 小时前
前端打包工具 - Rollup 打包工具笔记
前端·笔记