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. 在滑动场景中,使用组件复用通常需要用该回调函数去更新组件的状态变量,因此在该回调函数中应避免耗时操作,否则会导致丢帧卡顿。最佳实践请参考主线程耗时操作优化指导-组件复用回调

其他搭配场景

链接

关于我们

关于青蓝逐码组织

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

相关推荐
工一木子27 分钟前
URL时间戳参数深度解析:缓存破坏与前端优化的前世今生
前端·缓存
半点寒12W2 小时前
微信小程序实现路由拦截的方法
前端
某公司摸鱼前端3 小时前
uniapp socket 封装 (可拿去直接用)
前端·javascript·websocket·uni-app
要加油哦~3 小时前
vue | 插件 | 移动文件的插件 —— move-file-cli 插件 的安装与使用
前端·javascript·vue.js
小林学习编程3 小时前
Springboot + vue + uni-app小程序web端全套家具商场
前端·vue.js·spring boot
柳鲲鹏3 小时前
WINDOWS最快布署WEB服务器:apache2
服务器·前端·windows
weixin-a153003083164 小时前
【playwright篇】教程(十七)[html元素知识]
java·前端·html
ai小鬼头4 小时前
AIStarter最新版怎么卸载AI项目?一键删除操作指南(附路径设置技巧)
前端·后端·github
一只叫煤球的猫5 小时前
普通程序员,从开发到管理岗,为什么我越升职越痛苦?
前端·后端·全栈
遇到困难睡大觉哈哈5 小时前
HarmonyOS 公共事件机制介绍以及多进程之间的通信实现(9000字详解)
华为·harmonyos