首页 > 解决方案 > 如果不使用默认值,则 Angular @HostListener 延迟单击直到给出输入

问题描述

我正在努力完成这项工作。我想要实现的是以下。

我有一个带有该指令检查的属性输入的指令,但如果没有给出输入,它会使用指令本身定义的一些默认值。但是点击处理本身总是发生在输入值到达之前。所以它总是检查错误的输入(默认输入)。我也尝试过使用一些 rxjs,但是有些问题。该指令如下所示。

如果我记录exceptions@Oninit订阅,它甚至不会记录任何内容。我如何调整我的指令以使其在需要时工作?

一些代码可以更好地理解

  private onChangeSub$ = new Subject<AutoSaveExceptions>();
  private readonly clicks$ = new Subject<HTMLElement>();
  private someStream$: Subscription;

  private subscription$: Subscription;

  ngOnChanges(changes: SimpleChanges) {
    if (changes && changes['exceptions'] && changes['exceptions'].firstChange === true) {
      this.onChangeSub$.next(changes['exceptions'].currentValue);
      console.log(changes['exceptions'].currentValue);
    }
  }

ngOnInit() {
    console.log('oninit');
    this.subscription$ = this.onChangeSub$.pipe(
      defaultIfEmpty(this.inlineDefaultExceptions)
      ).subscribe((exceptions) => {
      this.exceptionAttributes = exceptions;
    });
    this.someStream$ = this.clicks$.pipe(
      delay(300),
    ).subscribe((target) => this.handleClicks(target));
  }

@HostListener('document:click', ['$event.target'])
  onClick(target: HTMLElement) {
    this.clicks$.next(target);
  }

@Edit: 没有指令的基本想法复制

标签: angularrxjsangular-directive

解决方案


首先,您必须避免@HostListener('document:click', ['$event.target'])一般使用。这可能成为主要性能问题的根源。原因是对于您的指令/组件的每个实例,您注册的文档点击次数与您拥有的指令/组件实例一样多,所有这些都会严重触发更改检测。小心那个。

如果你想听全局点击,你应该做的是这样的:

const documentClick$: Observable<MouseEvent> = fromEvent(document, 'click').pipe(publish(), refCount());
export const DOCUMENT_CLICK = new InjectionToken('DOCUMENT_CLICK', {providedIn: 'root', factory: () => documentClick$});

然后将其注入到您的组件/指令中:

constructor(@Inject(DOCUMENT_CLICK) private readonly documentClick$: Observable) {}

然后你可以用它做任何类型的 rxjs 魔法,它会确保你在整个应用程序中最多只有一个文档点击监听器。更少的变更检测运行 - 更好的性能。

现在您可以过滤您的 click$ 流,直到您进行更改:

this.documentClick$.pipe(
  withLatestFrom(this.onChangeSub$) // should not emit anything further until this stream emits, if it does, just add a filter
  filter(([event, changes]) => ... ) // check that it's not default
).subscribe(() => ...) // handle there for example

编辑:elementRef您的指令可以检查编辑状态并与我上面提到的一起 注入documentClick$,然后当启用编辑时,指令可以侦听全局单击并以检查它是否在我们的元素之外进行处理,如果是则触发将导致自动保存的事件. 这是stackblitz 链接


推荐阅读