我创建了一个 Stackblitz (https://stackblitz.com/edit/stackblitz-starters-xxbp1t?file=src%2Fmain.ts) 来演示我的多嵌套菜单的问题,但基本问题是当用户将鼠标悬停在“选项 3”上时,子菜单会正确显示,但位置错误。我怎样才能让子菜单与之前选择的选项一致,如下所示:
您不需要任何角度代码,主要是为了
hiding/showing
,请在下面找到一个使用CSS作为位置的工作示例。如有疑问请告诉我!
家长
import { Component } from '@angular/core';
import { bootstrapApplication } from '@angular/platform-browser';
import 'zone.js';
import { MenuComponent } from './menu/menu';
@Component({
selector: 'app-root',
standalone: true,
imports: [MenuComponent],
template: `
<button (click)="buttonClicked($event)">Open Menu</button>
<app-menu [display]="displayStyle" (menuItemSelected)="displayStyle='none'">
`,
})
export class App {
displayStyle = 'none';
buttonClicked(evt: MouseEvent) {
evt.stopPropagation();
if (this.displayStyle === 'block') {
this.displayStyle = 'none';
} else {
this.displayStyle = 'block';
}
}
}
bootstrapApplication(App);
菜单ts
// context-menu.component.ts
import { CommonModule } from '@angular/common';
import { Component, EventEmitter, Input, Output } from '@angular/core';
export interface MenuItem {
label: string;
position?: any;
action?: () => void;
subItems?: MenuItem[];
showSubMenu?: boolean; // Property to control submenu visibility
}
@Component({
selector: 'app-menu',
templateUrl: './menu.html',
styleUrls: ['./menu.scss'],
standalone: true,
imports: [CommonModule],
})
export class MenuComponent {
@Input() public display = 'none';
@Output() public menuItemSelected = new EventEmitter<MenuItem>();
public menuItems: MenuItem[] = [
{ label: 'Option 1', action: () => this.doSomething('Option 1') },
{
label: 'Option 2 Mega thing',
action: () => this.doSomething('Option 2'),
},
{
label: 'Option 3',
subItems: [
{
label: 'Sub Option 1',
action: () => this.doSomething('Sub Option 1'),
},
{
label: 'Sub Option 2',
subItems: [
{
label: 'Sub-Sub Option 1',
action: () => this.doSomething('Sub-Sub Option 1'),
},
],
},
],
},
];
public onMenuItemClick(event: MouseEvent, item: MenuItem): void {
this.menuItemSelected.emit(item);
}
private doSomething(what: string): void {
console.log(what);
}
}
菜单 html
<ng-template
#recursiveMenu
let-menuItems="menuItems"
let-root="root"
let-display="display"
>
<div
class="context-menu"
[ngClass]="{'child' : !root }"
[style.display]="display"
>
<ul [ngClass]="{'child' : !root }">
<li
*ngFor="let item of menuItems"
(click)="onMenuItemClick($event, item)"
style="position: relative"
>
{{ item.label }}
<i
class="expand-icon"
*ngIf="item.subItems && item.subItems.length > 0 "
></i>
<ng-container *ngIf="item.subItems && item.subItems.length > 0 ">
<div
[ngTemplateOutlet]="recursiveMenu"
[ngTemplateOutletContext]="{menuItems: item.subItems, position: item.position }"
></div>
</ng-container>
</li>
</ul>
</div>
</ng-template>
<div
[ngTemplateOutlet]="recursiveMenu"
[ngTemplateOutletContext]="{menuItems: menuItems, root: true, display: display || 'block'}"
></div>
菜单SCSS
.context-menu ul {
position: absolute;
z-index: 1000;
min-width: 150px;
background-color: white;
border: 1px solid #ddd;
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);
padding: 0;
margin: 0;
list-style: none;
list-style-type: none;
}
.context-menu ul li {
position: relative;
padding: 10px 20px;
cursor: pointer;
background-color: #fff;
}
.context-menu ul li:hover {
background-color: #f1f1f1;
}
.expand-icon {
font-size: 1.2em;
font-weight: bold;
float: right;
}
.child {
position: absolute;
left: 100%;
top: 0px;
}
.context-menu.child {
display: none;
}
li:hover > .context-menu.child {
display: inline;
}