Repeat:子组件复用

2024-11-10 11:20:47
10次阅读
0个评论

Repeat:子组件复用

Repeat组件non-virtualScroll场景(不开启virtualScroll开关)中,Repeat基于数据源进行循环渲染,需要与容器组件配合使用,且接口返回的组件应当是允许包含在Repeat父容器组件中的子组件。Repeat循环渲染和ForEach相比有两个区别,一是优化了部分更新场景下的渲染性能,二是组件生成函数的索引index由框架侧来维护。

Repeat组件virtualScroll场景中,Repeat将从提供的数据源中按需迭代数据,并在每次迭代过程中创建相应的组件,必须与滚动类容器组件配合使用。当在滚动类容器组件中使用了Repeat,框架会根据滚动容器可视区域按需创建组件,当组件滑出可视区域外时,框架会缓存组件,并在下一次迭代中使用。

使用限制

  • Repeat使用键值作为标识,因此键值生成函数key()必须针对每个数据生成唯一的值。
  • Repeat virtualScroll场景必须在滚动类容器组件内使用,仅有ListGridSwiper以及WaterFlow组件支持virtualScroll场景(此时配置cachedCount会生效)。其它容器组件只适用于non-virtualScroll场景。
  • Repeat开启virtualScroll后,在每次迭代中,必须创建且只允许创建一个子组件。不开启virtualScroll没有该限制。生成的子组件必须是允许包含在Repeat父容器组件中的子组件。
  • 当Repeat与@Builder混用时,必须将RepeatItem类型整体进行传参,组件才能监听到数据变化,如果只传递RepeatItem.itemRepeatItem.index,将会出现UI渲染异常。
  • template模板目前只支持virtualScroll场景。当多个template type相同时,Repeat会覆盖旧的template()函数,仅生效最新的template()
  • totalCount > array.length时,在父组件容器滚动过程中,应用需要保证列表即将滑动到数据源末尾时请求后续数据,直到数据源全部加载完成,否则列表滑动的过程中会出现滚动效果异常。解决方案见totalCount值大于数据源长度

键值生成规则

键值生成函数key()的目的是允许Repeat识别数组更改的细节:添加了哪些数据、删除了哪些数据,以及哪些数据改变了位置(索引)。

开发者使用建议:

  • 即使数据项有重复,开发者也必须保证键值key唯一(即使数据源发生变化);
  • 每次执行key()函数时,使用相同的数据项作为输入,输出必须是一致的;
  • key()中使用index是允许的,但不建议这样使用。原因是数据项移动时索引发生变化,即键值发生变化。因此Repeat会认为数据项发生了变化,并触发UI重新渲染,会降低性能表现;
  • 推荐将简单类型数组转换为类对象数组,并添加一个readonly id属性,在构造函数中给它赋一个唯一的值。

接下来主要看一下上面两种场景下的简单使用,

使用场景

non-virtualScroll数据展示&操作

数据源变化

@Entry
@ComponentV2
struct Parent {
  @Local simpleList: Array<number> = [];

  aboutToAppear(): void {


    for (let i = 1; i <= 100; i++) {
      this.simpleList.push(i);
    }

  }

  build() {

    Scroll(){
      Column() {
        Text('点击修改第3个数组项的值')
          .fontSize(24)
          .fontColor(Color.Red)
          .onClick(() => {
            this.simpleList[2] = 99;
          })

        Repeat<number>(this.simpleList)
          .each((obj: RepeatItem<number>) => {
            ChildItem({ item: obj.item })
              .margin({ top: 20 })
          })
          .key((item: number) => item.toString())
      }
      .justifyContent(FlexAlign.Center)

    }

  }
}

@ComponentV2
struct ChildItem {
  @Param @Require item: number;

  build() {
    Text(this.item.toString())
      .fontSize(30).width("100%").textAlign(TextAlign.Center)
  }
}

备注

作者:夏天

链接:https://www.nutpi.net/

出处:https://www.arkui.club/

来源:坚果派

著作权归作者所有,禁止任何未经授权的个人或组织以任何形式将本案例集及其附属资料、创新、创意、架构设计、算法、衍生作品等用于任何商业目的、盈利活动、各类竞赛(比赛)、直播教学、录播教学、线下课程、书籍编写、教材编写、会议、培训、公益活动、项目课题、毕业设计、毕业论文、学术论文等。商业转载请联系作者获得授权,非商业转载请注明出处。否则追究相关责任。

收藏00

登录 后评论。没有帐号? 注册 一个。