在Angular与Bootstrap中实现导航悬停下拉框的按钮可点击功能
导航下拉框无法点击按钮及自动隐藏问题解决
问题描述
- 当前行为:鼠标悬停导航项时,下拉容器显示,但容器内的按钮无法点击。
- 预期行为:悬停导航项时可点击下拉容器内的按钮;鼠标移出导航项和下拉容器范围后,容器自动隐藏。
问题原因
下拉容器与导航项是完全独立的DOM元素,当鼠标从导航项移动到下拉容器时,会立刻触发导航项的mouseleave事件,导致下拉容器被隐藏,因此无法完成按钮点击操作。同时两者不属于同一父容器,无法共享hover状态。
解决方案
方案1:调整DOM结构(推荐)
将下拉容器嵌套到对应导航项的父元素内部,这样鼠标在导航项和下拉容器之间移动时,不会触发mouseleave事件(因为它们属于同一个父元素的hover范围)。
修改后的HTML代码:
<div class="flex-container"> <div *ngFor="let item of navigations"> <ng-container *ngIf="item.type == 'dropdown'"> <div class="dropdown p-0 position-relative" (mouseenter)="showDropdown(item)" (mouseleave)="hideDropdown(item)" > <a class="cs-link-white dropdown-toggle" href="#" role="button" aria-expanded="false" > {{ item.menuTitle }} </a> <!-- 下拉容器移至导航项内部 --> <div *ngIf="activeMenu?.menuCode === item.menuCode" style="height: 200px; width: 100%; background-color: #c8c8c8;" class="dropdown-menu position-absolute" [class.show]="isDropdownOpen[item.menuCode]" > <div> Hello from {{ item.menuCode }} <button (click)="triggerAction()">Button</button> </div> </div> </div> </ng-container> <ng-container *ngIf="item.type == 'link'"> <div> <a class="cs-link-white" href="#">{{ item.menuTitle }}</a> </div> </ng-container> </div> </div>
补充CSS定位样式:
.dropdown.position-relative { position: relative; } .dropdown-menu.position-absolute { position: absolute; top: 100%; left: 0; margin: 0; z-index: 1000; }
方案2:定时器延迟隐藏(无需修改DOM结构)
如果无法调整DOM结构,可以通过定时器延迟下拉容器的隐藏,同时监听下拉容器的鼠标事件来控制显示状态:
修改后的TypeScript代码:
import { CommonModule } from '@angular/common'; import { Component, ElementRef, ViewChild } from '@angular/core'; interface NavigationItem { menuTitle: string; menuCode: string; type: 'dropdown' | 'link'; } @Component({ selector: 'app-navigation', templateUrl: './navigation.component.html', styleUrls: ['./navigation.component.css'], standalone: true, imports: [CommonModule], }) export class NavigationComponent { activeMenu!: NavigationItem; hideTimer: any; isDropdownOpen: any = { dropdown1: false, dropdown2: false, dropdown3: false, }; navigations: NavigationItem[] = [ { menuTitle: 'Dropdown 1', menuCode: 'dropdown1', type: 'dropdown' }, { menuTitle: 'Dropdown 2', menuCode: 'dropdown2', type: 'dropdown' }, { menuTitle: 'Dropdown 3', menuCode: 'dropdown3', type: 'dropdown' }, { menuTitle: 'Link1', menuCode: 'link1', type: 'link' }, { menuTitle: 'Link2', menuCode: 'link2', type: 'link' }, ]; @ViewChild('dropdownContainer') dropdownContainer!: ElementRef; showDropdown(item: NavigationItem) { clearTimeout(this.hideTimer); this.activeMenu = item; this.isDropdownOpen[item.menuCode] = true; } hideDropdown(item: NavigationItem) { this.hideTimer = setTimeout(() => { this.isDropdownOpen[item.menuCode] = false; }, 300); } onDropdownEnter() { clearTimeout(this.hideTimer); } onDropdownLeave() { if (this.activeMenu) { this.isDropdownOpen[this.activeMenu.menuCode] = false; } } triggerAction() { console.log('button clicked'); } }
对应的HTML修改(添加鼠标事件监听):
<div class="flex-container"> <div *ngFor="let item of navigations"> <ng-container *ngIf="item.type == 'dropdown'"> <div class="dropdown p-0" (mouseenter)="showDropdown(item)" (mouseleave)="hideDropdown(item)" > <a class="cs-link-white dropdown-toggle" href="#" role="button" aria-expanded="false" > {{ item.menuTitle }} </a> </div> </ng-container> <ng-container *ngIf="item.type == 'link'"> <div> <a class="cs-link-white" href="#">{{ item.menuTitle }}</a> </div> </ng-container> </div> </div> <div *ngIf="activeMenu" style="height: 200px; width: 100%; background-color: #c8c8c8;" class="dropdown-menu" [class.show]="isDropdownOpen[activeMenu.menuCode]" (mouseenter)="onDropdownEnter()" (mouseleave)="onDropdownLeave()" #dropdownContainer > <div> Hello from {{ activeMenu.menuCode }} <button (click)="triggerAction()">Button</button> </div> </div>
界面截图

内容的提问来源于stack exchange,提问作者Vijai S
相关产品推荐
相关产品推荐

