首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >Angular虚拟滚动:当到达滚动末尾时添加新项目

Angular虚拟滚动:当到达滚动末尾时添加新项目
EN

Stack Overflow用户
提问于 2019-02-20 00:17:49
回答 2查看 17.2K关注 0票数 17

我想在我的Angular应用程序上使用虚拟滚动。我的列表中的项目是远程分页搜索的结果。我想要加载更多的结果(调用下一页),每次我到达最后的视口滚动。

这是我的模板:

代码语言:javascript
代码运行次数:0
运行
复制
<div class="container">
    <cdk-virtual-scroll-viewport itemSize="100">
        <li *cdkVirtualFor="let item of searchResult">{{item}}</li>
    </cdk-virtual-scroll-viewport>
</div>

以下是我的一些尝试,让它在我需要的时候工作:

代码语言:javascript
代码运行次数:0
运行
复制
export class SearchComponent {
    @ViewChild(CdkVirtualScrollViewport) virtualScroll: CdkVirtualScrollViewport;
    searchPageNumber: number;
    searchResults: Array<any>;

    constructor(private scrollDispatcher: ScrollDispatcher, private searchService: SearchService) {
        this.searchPageNumber = 0;
        this.searchResults = [];
    }

    ngOnInit(): void {
        this.nextSearchPage(this.searchPageNumber);
    }

    ngAfterViewInit(): void {
        //this.scrollDispatcher.register(this.scrollable);
        //this.scrollDispatcher.scrolled(1000)
        //    .subscribe((viewport: CdkVirtualScrollViewport) => {
        //        console.log('scroll triggered', viewport);
        //    });

        this.virtualScroll.renderedRangeStream.subscribe(range => {
            console.log('range', range);
            console.log('range2', this.virtualScroll.getRenderedRange());
            if (this.virtualScroll.getRenderedRange().end % 10 === 0) {
                this.nextSearchPage(++this.searchPageNumber);
            }
        });
    }

    nextSearchPage(pageNumber: number): void {
        this.searchService.getResults(pageNumber).then((pagedResults) => {
            this.searchResults = this.searchResults.concat(pageResuls);
        });
    }
}

如您所见,只有当滚动条到达列表中当前呈现项的末尾时,我才知道如何触发对nextSearchPage函数的调用(以加载更多结果)。

你知道我该怎么做吗?

角度滚动文档很差,而且缺乏示例,正如本issue中所述。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-02-24 01:27:36

CdkScrollable上有一个函数measureScrollOffset可能会有所帮助。您可以订阅滚动事件并检查偏移量,以确定滚动到的位置。

代码语言:javascript
代码运行次数:0
运行
复制
  ngAfterViewInit(): void {
    this.scrollDispatcher.scrolled().pipe(
      filter(event => this.virtualScroll.measureScrollOffset('bottom') === 0)
    ).subscribe(event => {
      this.searchPageNumber++;
      this.nextSearchPage(this.searchPageNumber); 
    })

并且需要在滚动项集合更改后手动调用detectChange。虽然我还没有找到解决方案,但有一个问题:滚动条在检测到更改后会返回到开始位置。

点击这里查看演示:https://stackblitz.com/edit/template-angular7-material-primeng-ckxgzs

编辑:

事实证明,监听滚动结束可能不是一个好主意。一个更好的方法是侦听呈现范围(我相信它是在DOM中呈现的实际项目)的变化。一旦呈现范围结束等于数据长度,就是向集合中添加更多数据的时间。这以某种方式解决了bar返回到开头的问题。

代码语言:javascript
代码运行次数:0
运行
复制
 ngAfterViewInit(): void {
    this.scrollDispatcher.scrolled().pipe(
      filter(event => this.virtualScroll.getRenderedRange().end === this.virtualScroll.getDataLength())
    ).subscribe(event => {
      this.searchPageNumber++;
      this.nextSearchPage(this.searchPageNumber);
    })

新的演示在这里:https://stackblitz.com/edit/template-angular7-material-primeng-fhikcf

老实说,我的想法来自:https://angularfirebase.com/lessons/infinite-virtual-scroll-angular-cdk/你可能可以在那里学到更多。

票数 16
EN

Stack Overflow用户

发布于 2020-01-30 21:06:22

解决此问题的最简单方法是使用scrolledIndexChange.

代码语言:javascript
代码运行次数:0
运行
复制
<cdk-virtual-scroll-viewport itemSize="500" (scrolledIndexChange)="nextBatch($event)">

$event是目前呈现元素的第一个索引。因此,当第一项的索引接近列表中项的末尾时,可以调用下一页

请记住,这些项具有固定的高度(itemSize),因此很容易确定一次呈现的元素的数量。

例如:

代码语言:javascript
代码运行次数:0
运行
复制
  nextBatch(index) {
    if (index + $itemsRenderAtTheMoment === this.items.length - 1) {
      this.page ++;
      this.loadMore();
    }
  }
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/54770671

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档