如何防止angular子组件的点击事件过早触发?

How to prevent angular child component’s click event from getting triggered too early?

我试图创建一个搜索栏组件,该组件在单击其父组件中的搜索图标后打开,并在单击搜索栏外部后关闭。然而,在点击打开图标后,它立即在搜索栏组件中触发了一个 (document:click) 事件,结果它关闭得太早了。

我通过在搜索栏组件中创建“searchMode”变量并设置超时(在 ngOnInit 中)在 100 毫秒后将其设置为 true 找到了解决此问题的方法。但是,我想知道,除了设置超时之外,是否有更好的解决方案?

(预期结果:用户单击导航组件中的搜索图标 —> 搜索栏组件显示在搜索图标的位置 —> 用户在搜索栏组件外部单击 —> 搜索栏消失,搜索图标再次出现)

navigation.component.ts


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

@Component({
  selector: 'app-navigation',
  templateUrl: './navigation.component.html',
  styleUrls: ['./navigation.component.scss'],
})
export class NavigationComponent implements OnInit {
  searchActive = false;

  constructor() {}

  ngOnInit(): void {}

  openSearchBar(): void {
    this.searchActive = true;
  }

  closeSearchBar() {
    this.searchActive = false;
  }
}

navigation.component.html

<div class="weather-app__navigation">
  <ul class="weather-app__navigation-list">
    <li class="weather-app__navigation-list__item">
      <i class="fas fa-bars bars-icon"></i>
    </li>
    <li class="weather-app__navigation-list__item">
      <ng-container
        *ngIf="searchActive; then searchBarContent; else searchIcon"
      ></ng-container>
    </li>
    <ng-template #searchBarContent
      ><app-search-bar (closeSearch)="closeSearchBar()"></app-search-bar
    ></ng-template>
    <ng-template #searchIcon
      ><i class="fas fa-search search-icon" (click)="openSearchBar()"></i
    ></ng-template>
    <li class="weather-app__navigation-list__item">
      <i class="fas fa-info-circle about-icon"></i>
    </li>
  </ul>
</div>

搜索-bar.component.ts

import {
  Component,
  OnInit,
  ElementRef,
  ViewChild,
  Output,
  EventEmitter,
} from '@angular/core';

@Component({
  selector: 'app-search-bar',
  templateUrl: './search-bar.component.html',
  styleUrls: ['./search-bar.component.scss'],
  host: {
    '(document:click)': 'onClick($event)',
  },
})
export class SearchBarComponent implements OnInit {
  searchMode = false;
  city = '';
  @ViewChild('searchBar') searchBar!: ElementRef;
  @Output() closeSearch = new EventEmitter();

  constructor() {}

  ngOnInit(): void {
    setTimeout(() => {
      this.searchMode = true;
    }, 100);
  }

  onSubmit() {
    console.log('submitted');
  }

  onClick(event: Event) {
    if (!this.searchMode) {
      return;
    }

    if (!this.searchBar.nativeElement.contains(event.target)) {
      this.closeSearch.emit();
    }
  }
}

搜索-bar.component.html

<div class="weather-app__search-bar" #searchBar>
  <form class="weather-app__search-bar__form" (ngSubmit)="onSubmit()">
    <input type="text" name="city" [(ngModel)]="city" placeholder="City Name" />
    <input type="submit" value="Submit" class="btn" />
  </form>
</div>

在搜索按钮上捕获的点击事件上使用event.stopPropogation(),这将防止事件冒泡。

https://developer.mozilla.org/en-US/docs/Web/API/Event/stopPropagation