所以当你点击汉堡包图标本身以外的任何地方时,我正试图隐藏导航菜单。我让它工作,以便当您单击汉堡图标时,菜单在显示和隐藏之间切换。如果您单击页面本身,它也会隐藏菜单。问题是,如果您单击导航栏本身(但在汉堡包图标外),它将不会隐藏菜单。我想我明白这是因为handleClick()函数正在寻找不包含事件目标的引用元素,但我不知道如何解决这个问题并仍然使其他一切正常工作。
以下是组件HTML文件:
<nav class="navbar fixed-top navbar-dark bg-primary">
<button class="navbar-toggler" type="button" (click)="toggleMenu()">
<span class="navbar-toggler-icon"></span>
</button>
<a class="navbar-brand pull-right" href="#">Job Matrix</a>
</nav>
<div class="form-row btn-group-vertical nav-menu-fixed" *ngIf="visible" [@fade-in-out]="state">
<a class="btn btn-primary text-left item" href="#" role="button">Jobs</a>
<a class="btn btn-primary text-left item" href="#" role="button">Resumes</a>
</div>
这是角度组件打字稿文件:
import { Component, OnInit, ElementRef } from '@angular/core';
import { trigger, group, state, style, animate, transition } from '@angular/animations';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations'
@Component({
selector: 'nav-menu',
templateUrl: './navmenu.component.html',
styleUrls: ['./navmenu.component.scss'],
host: {
'(document:click)': 'handleClick($event)',
},
animations: [
trigger('fade-in-out', [
state('open', style({
transform: 'translate3d(0, 0, 0)'
})),
state('closed', style({
transform: 'translate3d(0, -110%, 0)'
})),
transition('closed => open', animate('500ms ease-in')),
transition('open => closed', animate('500ms ease-out'))
])
]
})
export class NavMenuComponent implements OnInit {
[x: string]: any;
visible: boolean;
state: string;
constructor(private ref: ElementRef) {
}
ngOnInit(): void {
this.visible = false;
this.state = 'closed';
}
toggleMenu() {
this.visible = true;
setTimeout(() => {
this.state = this.state == "open" ? 'closed' : 'open';
}, 50);
}
handleClick(event: Event) {
if (!this.ref.nativeElement.contains(event.target)) {
this.state = 'closed';
setTimeout(() => {
this.visible = false;
}, 500);
}
}
}
答案 0 :(得分:0)
现在,ref
正在为您提供整个主机元素(汉堡包和菜单),但似乎您要将菜单(.nav-menu-fixed
)分开,如果点击位于菜单之外(包括.navbar-toggler
),关闭菜单。您可以使用@ViewChild
装饰器来获取菜单本身,并检查点击是否包含菜单。
将ref(#menu
)添加到菜单组件中:
<div #menu class="nav-menu-fixed" *ngIf="visible" [@fade-in-out]="state">
<a class="btn btn-primary text-left item" href="#" role="button">Jobs</a>
<a class="btn btn-primary text-left item" href="#" role="button">Resumes</a>
</div>
然后使用@ViewChild
装饰器查询DOM中的菜单元素。
export class NavMenuComponent implements OnInit {
@ViewChild('menu', {read: ElementRef})
menu: ElementRef;
constructor() {}
@HostListener('document:click', ['$event'])
handleClick(event: Event) {
const menuIsOpen = this.visible && this.state === 'open';
const toggleWasClicked = this.toggle.nativeElement.contains(event.target);
const menuWasClicked = this.menu && this.menu.nativeElement.contains(event.target);
const pageWasClicked = !toggleWasClicked && !menuWasClicked;
const menuShouldClose = (pageWasClicked || toggleWasClicked) && menuIsOpen;
if (menuShouldClose) {
this.state = 'closed';
setTimeout(() => {
this.visible = false;
}, 500);
}
}
}
我在我的代码段中使用了@HostListener
装饰器而不是host
属性,因为我认为将事件侦听器靠近处理它的方法是一种很好的方法:)