如何防止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
我试图创建一个搜索栏组件,该组件在单击其父组件中的搜索图标后打开,并在单击搜索栏外部后关闭。然而,在点击打开图标后,它立即在搜索栏组件中触发了一个 (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