基于ng-zorro table滚动无限加载

发布时间 2023-06-11 21:05:09作者: 想学前端的小李

首先复制一下ng-zorro的虚拟表格

这里选用虚拟表格,原因是数据页面有多个表格存在加载的数据量很大,且表格滚动时有事件监听不用写额外的方法去监听滚动条滚动

 先打印分析表格滚动时有哪些信息被输出

从打印的信息内发现有个_renderedRange属性名为渲染的范围,因此可以通过该属性的end值来判断当前表格已经滚动到底部,因此我们先获取下_renderedRange的end值

但是打印时发现_renderedRange为私有属性无法直接获取

 这里我们先用//@ts-ignore忽略下语法检查

 滚动到底部正常打印100(当前只有100条数据)

 但用//@ts-ignore这种方法是不可取的,因此我们点进cdkVirtualScrollViewport看看有没有方法返回了_renderedRange的值

因为angular内部源码基本都是面向对象的编程,因此可以尝试搜索下getrenderedRang

 因此_renderedRange值可以通过getRenderedRange()方法来获取end值

 

 正常获取end值 ,此时可以通过判断end值是否等于当前数据集合长度来加载数据

效果

优化下在表格最下方加入加载的标志提醒用户在加载

 效果

 当然还有后端已经查不到数据了,给用户相应的提示或者去控制不用在查询接口了剩下就自己优化啦

下面是实现的代码

<nz-table
  #virtualTable
  [nzBordered]="true"
  [nzVirtualItemSize]="54"
  [nzData]="listOfData"
  [nzVirtualForTrackBy]="trackByIndex"
  [nzFrontPagination]="false"
  [nzShowPagination]="false"
  [nzScroll]="{ x: '1200px', y: '240px' }"
>
  <thead>
    <tr>
      <th nzLeft>Full Name</th>
      <th nzLeft>Age</th>
      <th>Index</th>
      <th>Column 1</th>
      <th>Column 2</th>
      <th>Column 3</th>
      <th>Column 4</th>
      <th>Column 5</th>
      <th>Column 6</th>
      <th>Column 7</th>
      <th>Column 8</th>
      <th nzRight>Action</th>
    </tr>
  </thead>
  <tbody>
    <ng-template nz-virtual-scroll let-data let-index="index">
      <tr>
        <td nzLeft>{{ data.name }}</td>
        <td nzLeft>{{ data.age }}</td>
        <td>{{ data.index }}</td>
        <td>{{ data.address }}</td>
        <td>{{ data.address }}</td>
        <td>{{ data.address }}</td>
        <td>{{ data.address }}</td>
        <td>{{ data.address }}</td>
        <td>{{ data.address }}</td>
        <td>{{ data.address }}</td>
        <td>{{ data.address }}</td>
        <td nzRight>
          <a>action</a>
        </td>
      </tr>
      <tr>
        <td colSpan="12" *ngIf="index == listOfData.length - 1">
          <nz-spin></nz-spin>
        </td>
      </tr>
    </ng-template>
  </tbody>
</nz-table>
import { ChangeDetectionStrategy, Component, ViewChild } from '@angular/core';
import { NzTableComponent } from 'ng-zorro-antd/table';
import { Subject, takeUntil } from 'rxjs';

@Component({
  selector: 'app-bottom-add-table-real',
  templateUrl: './bottom-add-table-real.component.html',
  styleUrls: ['./bottom-add-table-real.component.less'],
})
export class BottomAddTableRealComponent {
  @ViewChild('virtualTable', { static: false })
  nzTableComponent?: NzTableComponent<any>;
  private destroy$ = new Subject<boolean>();
  listOfData: any[] = [];

  scrollToIndex(index: number): void {
    this.nzTableComponent?.cdkVirtualScrollViewport?.scrollToIndex(index);
  }

  trackByIndex(_: number, data: any): number {
    return data.index;
  }

  ngOnInit(): void {
    const data = [];
    for (let i = 0; i < 100; i++) {
      data.push({
        index: i,
        name: `Edward`,
        age: i,
        address: `London`,
      });
    }
    this.listOfData = data;
  }

  ngAfterViewInit(): void {
    this.nzTableComponent?.cdkVirtualScrollViewport?.scrolledIndexChange
      .pipe(takeUntil(this.destroy$))
      .subscribe(() => {
        const end =
          this.nzTableComponent?.cdkVirtualScrollViewport?.getRenderedRange()
            .end;

        if (end === this.listOfData.length) {
          this.getData();
        }
      });
  }
  timer: any = null;
  getData() {
    if (!this.timer) {
      this.timer = setTimeout(() => {
        const data = [];
        for (let i = 0; i < 100; i++) {
          data.push({
            index: i,
            name: `Edward`,
            age: i,
            address: `London`,
          });
        }
        this.listOfData = [...this.listOfData, ...data];
        clearTimeout(this.timer);
        this.timer = null;
      }, 2000);
    }
  }
  ngOnDestroy(): void {
    this.destroy$.next(true);
    this.destroy$.complete();
  }
}