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

其他搭配场景

链接

关于我们

关于青蓝逐码组织

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

相关推荐
RFCEO6 分钟前
前端编程 课程十三、:CSS核心基础1:CSS选择器
前端·css·css基础选择器详细教程·css类选择器使用方法·css类选择器命名规范·css后代选择器·精准选中嵌套元素
烬头882130 分钟前
React Native鸿蒙跨平台采用了函数式组件的形式,通过 props 接收分类数据,使用 TouchableOpacity实现了点击交互效果
javascript·react native·react.js·ecmascript·交互·harmonyos
Amumu1213830 分钟前
Vuex介绍
前端·javascript·vue.js
We་ct31 分钟前
LeetCode 54. 螺旋矩阵:两种解法吃透顺时针遍历逻辑
前端·算法·leetcode·矩阵·typescript
qq_177767371 小时前
React Native鸿蒙跨平台通过Animated.Value.interpolate实现滚动距离到动画属性的映射
javascript·react native·react.js·harmonyos
2601_949480061 小时前
【无标题】
开发语言·前端·javascript
css趣多多1 小时前
Vue过滤器
前端·javascript·vue.js
理人综艺好会2 小时前
Web学习之用户认证
前端·学习
We་ct2 小时前
LeetCode 36. 有效的数独:Set实现哈希表最优解
前端·算法·leetcode·typescript·散列表
qq_177767372 小时前
React Native鸿蒙跨平台实现消息列表用于存储所有消息数据,筛选状态用于控制消息筛选结果
javascript·react native·react.js·ecmascript·harmonyos