javascript - 在 Angular 中使用单击事件处理多个组件

标签 javascript angular typescript

这个问题一直让我抓狂。我有两个组件,它们都是同一页面上的可切换下拉菜单。我对这两个组件都有类似的东西:

@HostListener('click', ['$event'])
clickInside() {
  event.stopPropagation();
  this.showMenu = true;
}

@HostListener('document:click')
clickOutside() {
  if (this.showMenu) {
    this.showMenu = false;
  }
}

它对于一个组件来说效果很好,但是当我在同一页面上有两个组件时,单击另一个组件将使第一个组件保持打开状态,结果是它们同时打开,这是我不希望的。原因当然是 event.stopPropagation(),但如果没有这个,组件内的点击也将是文档内的点击。

最佳答案

当我们单击组件内部时 - 它应该打开,当单击外部时 - 它应该关闭。

  constructor(private elementRef: ElementRef){}

  @HostListener('click')
  clickInside() {
    this.showMenu = true;
  }

  @HostListener('document:click', ['$event'])
  clickOutside(event) {
    if (this.showMenu && this.isClickOutside(event)) {
      this.showMenu = false;
    }
  }

  private isClickOutside(event: MouseEvent): boolean {
    return !this.elementRef.nativeElement.contains(event.target);
  }

该解决方案至少有一个缺点 - 每个在文档上具有监听器的组件都会导致额外的更改检测周期。为了防止这种情况,我们应该处理 Angular 之外的事件,但更改内部的状态。

private readonly onDestroy$ = new Subject();

constructor( private ngZone: NgZone,) {}

ngOnInit() {
    this.ngZone.runOutsideAngular(() => {
      fromEvent(window.document, 'click')
        .pipe(
          filter(
            (event: MouseEvent) =>
              this.isOpen() && this.isClickOutside(event)
          ),
          takeUntil(this.onDestroy$),
        )
        .subscribe(() => {
          this.ngZone.run(() => {
            this.close();
          });
        });
    });
  }

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

关于javascript - 在 Angular 中使用单击事件处理多个组件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52108773/

相关文章:

javascript - 将多个 div 元素包裹在同一个类中

Angular 如何根据路线更改导航菜单标题

angular - 如何在 Angular 中匹配 toHaveBeenCalledWith 中的部分 url

javascript - Angular 2 智能表动态数据不加载

javascript - 条形图中的链接 (charts.js)

javascript - Power BI API 身份验证

javascript - 不显示此警报 ---> 警报 ("I am inside change");

arrays - [首先,...休息] : A spread argument must either have a tuple type or be passed to a rest parameter. ts(2556)

angular - mat-date-range-input 不是已知元素 [Angular Material ]

在 array.map 内部分配时,Javascript onClick 不触发