Angular自定义右键菜单:点击菜单项无法显示正确索引求助
问题描述
实现自定义右键菜单时,列表中任意条目右键点击后,点击菜单项总是显示最后一个条目索引(例如3个条目时始终显示2),需要让菜单项显示对应条目的正确索引。
现有代码
父组件 HTML
<div *ngFor="let item of items; let i = index" (contextmenu)="displayContextMenu($event); false"> <span> {{item}}</span> <app-context-menu *ngIf="rightClickMenuItems.length > 0 && isDisplayContextMenu" [ngStyle]="getRightClickMenuStyle()" [contextMenuItems]="rightClickMenuItems" (onContextMenuItemClick)="handleMenuItemClick($event, i)" ></app-context-menu> </div>
父组件 TS
items = ["item0","item1","item2"]; isDisplayContextMenu!: boolean; rightClickMenuItems: Array<ContextMenu> = []; rightClickMenuPositionX!: number; rightClickMenuPositionY!: number; displayContextMenu(event: any) { this.isDisplayContextMenu = true; this.rightClickMenuItems = [ { menuText: 'Print index', menuEvent: 'Handle print index', }, ]; this.rightClickMenuPositionX = event.clientX; this.rightClickMenuPositionY = event.clientY; } handleMenuItemClick(event: any, index: number) { switch (event.data) { case this.rightClickMenuItems[0].menuEvent: this.printIndex(index); break; } } printIndex(index: number){ alert(index); } @HostListener('document:click') documentClick(): void { this.isDisplayContextMenu = false; } getRightClickMenuStyle() { return { position: 'fixed', left: `${this.rightClickMenuPositionX}px`, top: `${this.rightClickMenuPositionY}px` } }
右键菜单组件 HTML
<ng-container> <div> <div *ngFor="let menuItem of contextMenuItems; index as i" (click)="onContextMenuClick($event, menuItem.menuEvent)"> {{ menuItem.menuText }} </div> </div> </ng-container>
右键菜单组件 TS
import { Component, Input, Output, EventEmitter } from '@angular/core'; import { ContextMenu } from '../../_models/contextMenu.model'; import { NgIf, NgFor } from '@angular/common'; @Component({ selector: 'app-context-menu', templateUrl: './context-menu.component.html', styleUrls: ['./context-menu.component.css'], standalone: true, imports: [NgIf, NgFor] }) export class ContextMenuComponent { @Input() contextMenuItems!: Array<ContextMenu>; @Output() onContextMenuItemClick: EventEmitter<any> = new EventEmitter<any>(); onContextMenuClick(event: any, data: any): any { this.onContextMenuItemClick.emit({ event, data, }); } }
模型文件
export interface ContextMenu { menuText: any; menuEvent: any; }
解决方案
问题根源
- 每个循环条目内都渲染了一个
app-context-menu,右键点击时所有菜单都会显示(重叠后看似一个),但点击时传递的i是循环最后一次的索引值。 - Angular变更检测机制导致点击菜单项时,
i已经指向最后一个条目。
修改步骤
- 将
app-context-menu移到*ngFor循环外部,只渲染一个菜单实例。 - 在右键点击时保存当前条目的索引,而非在菜单项点击时传递索引。
修改后的代码
父组件 HTML
<div *ngFor="let item of items; let i = index" (contextmenu)="displayContextMenu($event, i); false"> <span> {{item}}</span> </div> <app-context-menu *ngIf="rightClickMenuItems.length > 0 && isDisplayContextMenu" [ngStyle]="getRightClickMenuStyle()" [contextMenuItems]="rightClickMenuItems" (onContextMenuItemClick)="handleMenuItemClick($event)" ></app-context-menu>
父组件 TS
items = ["item0","item1","item2"]; isDisplayContextMenu!: boolean; rightClickMenuItems: Array<ContextMenu> = []; rightClickMenuPositionX!: number; rightClickMenuPositionY!: number; currentIndex!: number; // 新增变量保存当前点击的条目索引 displayContextMenu(event: any, index: number) { // 新增index参数接收当前条目索引 this.currentIndex = index; // 保存当前索引 this.isDisplayContextMenu = true; this.rightClickMenuItems = [ { menuText: 'Print index', menuEvent: 'Handle print index', }, ]; this.rightClickMenuPositionX = event.clientX; this.rightClickMenuPositionY = event.clientY; } handleMenuItemClick(event: any) { // 移除index参数 switch (event.data) { case this.rightClickMenuItems[0].menuEvent: this.printIndex(this.currentIndex); // 使用保存的当前索引 break; } } // 其余代码保持不变
这样修改后,右键点击任意条目时,会保存对应的索引,点击菜单项时就会弹出正确的条目索引。
内容的提问来源于stack exchange,提问作者user6781
相关产品推荐
相关产品推荐

