Angular中使用Intersection Observer API实现无限滚动

背景:
实现原理为 在data下面加一个loading元素 如果此元素进入视窗 则调用api获取新的数据加到原来的数据里面,这时loading就会被新数据顶下去,如此循环。

<div id="dataContainer"></div>
<div id="loadingContainer"></div>

传统angular实现是使用ngAfterViewInit()生命周期,写在指令(Directive)里面,并且传出一个事件,触发时回调被监控组件里面的具体函数。

不过对于异步操作,元素可能在ngAfterViewInit被调用时还没有完成初始化而导致bug,所以用ngAfterViewChecked() 会更稳,当然也更会导致性能问题,每次变更检测它都被调用,这可能会增加应用程序的负载。

所以这里使用h5 提供的新API ——交叉观察器 API(Intersection Observer API)提供了一种异步检测目标元素与祖先元素或顶级文档的视口相交情况变化的方法。

效果如图,为了截到loading,我在增加数据的函数里面加了个等待。
在这里插入图片描述

上代码

watch-to-view.directive.ts

import {
    Directive, Output,EventEmitter, ElementRef } from '@angular/core';

@Directive({
   
  selector: '[appWatchToView]'
})
export class WatchToViewDirective {
   
  private observer:IntersectionObserver;
  @Output() appWatchToView = new EventEmitter<IntersectionObserverEntry>();

  constructor(public el:ElementRef) {
   
    this.observer = new IntersectionObserver(this.callback,{
   rootMargin:'100px',threshold:1,root:null});
    this.observer.observe(el.nativeElement);
   }
  public callback = (entries: IntersectionObserverEntry[]) => {
   
    entries.forEach((entry: IntersectionObserverEntry) => {
   
      if (entry.isIntersecting) {
   
        this.appWatchToView.emit(entry);
      }
    })
  }

}

app.component.html

<div id="dataContainer">
    <ul>
        <li class="blueBox" *ngFor="let i of data">{
   {
   i}}</li>
    </ul>
</div>
<div id="loadingContainer" class="blueBox" appWatchToView (appWatchToView)="this.loadObserver($event)">Loading more...</div>

app.component.ts

import {
    Component } from '@angular/core';

@Component({
   
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
   
  title = 'Tour of Herors';
  batch:Number = 10;
  len:Number = this.batch;
  data:Array<Number>=new Array(this.batch).fill(0).map((_,i)=>i);
  loadObserver = async function (event){
   
    console.log(event.target);
    await new Promise(resolve => setTimeout(resolve, 1000));
    this.data.push(...new Array(this.batch).fill(0).map((_,i)=>i+this.len));
    this.len+=this.batch;
  }
}

再给个样式吧

  .blueBox{
   
    display: block;
    width: 100%;
    height: 100px;
    background-color: #38b1ee;
    margin-top: 5px;
    text-align: center;
    color: white;
    font-size: large;
  }

官方link: https://developer.mozilla.org/zh-CN/docs/Web/API/Intersection_Observer_API

相关推荐

  1. 摒弃传统分页:移动端开发无限滚动实现

    2023-12-16 23:56:02       35 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2023-12-16 23:56:02       98 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2023-12-16 23:56:02       106 阅读
  3. 在Django里面运行非项目文件

    2023-12-16 23:56:02       87 阅读
  4. Python语言-面向对象

    2023-12-16 23:56:02       96 阅读

热门阅读

  1. c++中的new与delete

    2023-12-16 23:56:02       70 阅读
  2. Shell三剑客:sed(简介)

    2023-12-16 23:56:02       62 阅读
  3. 半导体:Gem/Secs基本协议库的开发(3)

    2023-12-16 23:56:02       54 阅读
  4. 基于BP神经网络的小车避障算法仿真与实现

    2023-12-16 23:56:02       55 阅读
  5. 包络检波的MATLAB实现

    2023-12-16 23:56:02       43 阅读
  6. ESP32网络编程实例-WebSocket服务器广播信息

    2023-12-16 23:56:02       69 阅读
  7. c#读取CSV文件跟Excel导入成DataTble

    2023-12-16 23:56:02       52 阅读
  8. Python实现数据库导出Excel并动态化sql时间

    2023-12-16 23:56:02       52 阅读
  9. 数据库基础学习04计算机二级-第四章 数据查询

    2023-12-16 23:56:02       56 阅读