Angular HostListener 只捕获一个事件

Posted

技术标签:

【中文标题】Angular HostListener 只捕获一个事件【英文标题】:Angular HostListener catch only one event 【发布时间】:2022-01-22 16:43:00 【问题描述】:

我正在使用 HostListener 在滚动时加载下一组数据,但是当我滚动到底部时,HostListener 会被多次调用,因此所有数据都已加载。到达页面底部时如何只调用一次?

  @HostListener('document:scroll', [])
  onScroll() 
    if ((window.innerHeight + window.scrollY * 1.1) >= document.body.offsetHeight) 
      //loading next 20 records 
    
  

【问题讨论】:

【参考方案1】:

要实现您想要的行为,您需要在用户停止滚动之前对检查进行去抖动,然后检查页面末尾的滚动位置。

我建议使用 setTimeout 或 RxJS 去抖动计算。

选项setTimeout

private timeoutID: number;

@HostListener('document:scroll', [])
onScroll() 

  if (timeoutID) 
    clearTimeout(timeoutID);
  
  
  // Delay execution for e.g. 300ms 
  setTimeout(() => 
    // Checks for end of page
    if ((window.innerHeight + window.scrollY * 1.1) >= document.body.offsetHeight) 
      //loading next 20 records 
    
  , 300);

只要用户停止滚动至少 300 毫秒,就会执行最新的 setTimeout

选项RxJS

private subs: Subscription;

ngOnInit()
  this.subs = fromEvent(document, 'scroll').pipe(

    // Delay execution by 300ms after the last event
    debounceTime(300),

    // Prevent execution of the subscription as long as the page end isn't reached
    filter(() => (window.innerHeight + window.scrollY * 1.1) >= document.body.offsetHeight)

  ).subscribe(() => 
    // Load the next 20 records
  );


ngOnDestroy()
  this.subs.unsubscribe();

只要用户停止滚动至少 300 毫秒,订阅才会在到达页面末尾时执行。

为了完整性,我展示了这两种方法,但我个人推荐RxJS 方法,因为我认为这种方法比另一种更干净。

【讨论】:

谢谢,这种方法会延迟一个事件,但它也会被多次调用,因此我的所有数据都已加载 您尝试过哪种方法?无论哪种方式看起来都很奇怪,请分享您的代码:)

以上是关于Angular HostListener 只捕获一个事件的主要内容,如果未能解决你的问题,请参考以下文章

Angular - 创建通用装饰器包装 @HostListener

Angular 8 @HostListener('window:scroll', []) 不工作

Angular - HostListener 指令和传递值

打字稿 | JavaScript | Angular 2:动态设置@HostListener 参数

Angular12 - 使用 @HostBinding 或 @HostListener 而不是 `host` 元数据属性

防止 Angular HostListener 传播到父组件