【问题标题】:Using ngx-virtual-scroller with sections of items将 ngx-virtual-scroller 与项目部分一起使用
【发布时间】:2020-02-10 13:52:17
【问题描述】:

我想对部分项目使用 ngx-virtual-scroller。

<virtual-scroller #scroll [items]="???">
    <div *ngFor="let group of groups;">    
       <div class="title">
            <span>{{group.name}}</span>
       </div>

       <my-item *ngFor="let item of group.items">
       </my-item>
     </div>
</virtual-scroller>

ngx-virtual-scroller的虚拟滚动的item里面应该放什么?

我需要为一组项目设置一个标题。每个项目都属于一个组。

即标题应该在自己的一行中,并且项目高度大于标题的高度。

已编辑:

我忘了提到组的数量是动态的,每个组中的项目数也是动态的。 另外,一个组中的项目数可能是一个非常大的数字,所以我不希望滚动的项目将是组,因为如果组很大,我不想加载所有的到 DOM。

【问题讨论】:

    标签: angular virtualscroll


    【解决方案1】:

    我知道您的问题是关于 ngx-virtual-scroller,但我有一个针对 ngx-ui-scroll 的解决方案,这可能对您或处理数据集分组的人有所帮助。大部分逻辑似乎独立于滚动器实现/api,但让我想我是为 ngx-ui-scroll 做的。

    在这种情况下,我们需要将groups 视为应根据ngx-ui-scroll 文档实现get 方法的数据源。喜欢关注

    groups = new Datasource({
      get: (index, count, success) =>
        success(this.getItems(index, count)
      )
    })
    

    我不知道您的数据结构,这应该不重要,因为我们正在讨论这种方法。我们唯一需要考虑的是数据源和模板之间的一致性。假设我们已经有了固定长度的平面项目数据集

    data = [];
    MIN = 1;
    MAX = 200;
    
    constructor() {
      for (let i = this.MIN; i <= this.MAX; i++) {
        this.data.push({ id: i, text: 'item #' + i });
      }
    }
    

    并且您想将它们分组。你会有多少组?这取决于您希望在一个组中包含多少个项目。

    this.ITEMS_PER_GROUP = 3;
    this.groupsCount = Math.ceil((this.MAX - this.MIN) / this.ITEMS_PER_GROUP);
    

    然后回到getItems 实现,我建议将项目检索过程拆分为2 个方法。获取组(通过 ngx-ui-scroll api 的索引计数):

    getItems(index: number, count: number) {
      const data = [];
      const start = Math.max(1, index);
      const end = Math.min(this.groupsCount, index + count - 1);
      if (start <= end) {
        for (let i = start; i <= end; i++) {
          const group = this.getGroup(i);
          if (group) {
            data.push(group);
          }
        }
      }
      return data;
    }
    

    并按索引获取一组:

    getGroup(index: number) {
      let result = null;
      const data = [];
      const start = this.MIN + (index - 1) * this.ITEMS_PER_GROUP;
      const end = start + this.ITEMS_PER_GROUP - 1;
      if (start <= end) {
        for (let i = start; i <= end; i++) {
          const item = this.data.find(item => item.id === i);
          if (item) {
            data.push(item);
          }
        }
        result = {
          title: 'Group ' + index,
          items: data
        };
      }
      return result;
    }
    

    这样您将获得与模板层所需的数据源一致的数据源。使用 ngx-ui-scroll 将如下所示:

    <div *uiScroll="let group of groups">
      <div>{{group.title}}</div>
      <div *ngFor="let item of group.items">
        <div class="item">{{item.text}}</div>
      </div>
    </div>
    

    说到 ngx-ui-scroll,所有的限制都可以消除,我的意思是你可能不知道数据集和组数的边界,但实现会略有不同。

    最后,我创建了演示,因为这个案例似乎对 ngx-ui-scroll 用户有用

    https://stackblitz.com/edit/angular-ngx-ui-scroll-1-3-4-grouping-datasource

    【讨论】:

    • 您好,感谢您的回答。我忘了提到我正在从其他服务中获取所有组。组的数量是动态的,每个组中的项目数是动态的,并且可能是组中的大量项目。这就是我不想做 items=groups 的原因,因为如果我有一个大组,我不想将所有这些都加载到 DOM。
    • @RoG 在这种情况下,我会尝试一种相反的方法,比如扁平化方法:制作一个额外的层,专门用于根据 app/scroller 累积向从组数组构建的滚动条提供一个项目数组要求,受平面项目列表索引限制,不受组索引限制。组标题可以被视为结果平面项目流中的另一个项目。
    • 是的,这就是我想做的,但我想知道是否有其他我没有想到的解决方案。此解决方案中的问题是标题应该在一行中,但项目可能是连续 5 个或更多/更少取决于屏幕的宽度......这应该是多列滚动和不相等的子项大小(标题大小与项目大小不同)。
    • @RoG 要求太具体了,这似乎可行,但恐怕没有一个现成的解决方案可以让你开箱即用,所以你必须实现它自己来
    猜你喜欢
    • 2019-11-17
    • 2022-12-14
    • 1970-01-01
    • 2018-06-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多