You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular中使用rxjs的fromEvent如何获取keyup的最后一次触发事件

问题根源

  • 你把事件订阅逻辑放在了ngAfterContentChecked生命周期钩子中,这个钩子会在Angular每次执行变更检测时反复触发,每触发一次就新增一个keyup事件的订阅,最终按一次按键会触发多个订阅的回调,输出多条日志。
  • 你当前的distinctUntilChanged没有传入对比逻辑,默认只对比引用,而每次keyup产生的事件对象都是新的引用,所以这个操作符现在完全没有生效。

修复方案

  1. 将事件订阅逻辑移到只会执行一次的ngAfterViewInit生命周期中,避免重复订阅
  2. 补充订阅销毁逻辑,避免组件销毁后内存泄漏
  3. 按需调整distinctUntilChanged的对比规则,只对比你关心的字段(比如按键值、输入框内容等)
  4. 如果需要捕获最后一次触发结果,保留debounceTime即可,它会在你停止触发事件指定时长后,抛出最后一次的事件对象

修复后的代码参考:

import { Directive, AfterViewInit, ElementRef, OnDestroy } from '@angular/core';
import { fromEvent, Subject } from 'rxjs';
import { distinctUntilChanged, debounceTime, takeUntil } from 'rxjs/operators';

@Directive({
  selector: '[appFocuser]'
})
export class FocuserDirective implements AfterViewInit, OnDestroy {
  focusableArray = [];
  parent = null;
  currentFocus: HTMLElement;
  // 用于销毁订阅的subject
  private destroy$ = new Subject<void>();

  constructor(private el: ElementRef) {}

  ngAfterViewInit() {
    this.parent = this.el.nativeElement;
    this.initFocus();
    this.initKeyupHandler();
  }

  // 单独抽离焦点初始化逻辑,有需要可以单独调用
  private initFocus() {
    this.focusableArray = Array.from(this.parent.querySelectorAll(`[data-focus=true]`));
    this.currentFocus = this.focusableArray[0] as HTMLElement;
    if (this.currentFocus) {
      this.currentFocus.focus();
    }
  }

  private initKeyupHandler() {
    fromEvent<KeyboardEvent>(this.parent, 'keyup')
      .pipe(
        debounceTime(100),
        // 这里示例对比按键code,你可以根据需求改成对比输入框的值等逻辑
        distinctUntilChanged((prev, curr) => prev.code === curr.code),
        // 组件销毁时自动取消订阅
        takeUntil(this.destroy$)
      )
      .subscribe(event => {
        // 这里只会输出防抖后的最后一次事件
        console.log(event);
        // 你的后续业务逻辑
      });
  }

  ngOnDestroy() {
    this.destroy$.next();
    this.destroy$.complete();
  }
}

内容的提问来源于stack exchange,提问作者3gwebtrain

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.30 23:24:04