移动端长按AngularJS锚点标签时阻止默认浏览器菜单弹出
Angular移动端长按锚点标签阻止浏览器默认菜单方案
你当前的指令里,event.preventDefault()放在setTimeout回调里执行的时机太晚了——这时候浏览器的长按默认菜单已经触发,根本拦不住。要解决这个问题,得调整阻止逻辑的时机,同时额外处理contextmenu事件(移动端长按本质会触发这个事件来弹出菜单)。
下面是修改后的完整指令代码,兼顾长按触发tooltip和阻止默认菜单,同时不影响锚点的正常短按跳转:
import { Directive, ElementRef, EventEmitter, HostListener, Output } from '@angular/core'; @Directive({ selector: '[appLongPress]' }) export class LongPressDirective { @Output() longPress = new EventEmitter<void>(); private timeoutId: any; private touchStartTime: number = 0; private contextMenuListener: (e: Event) => void; constructor(private elementRef: ElementRef) { // 提前定义contextmenu的处理函数,方便后续添加/移除监听 this.contextMenuListener = (e) => { e.preventDefault(); e.stopPropagation(); }; } @HostListener('touchstart', ['$event']) onTouchStart(event: TouchEvent) { this.touchStartTime = Date.now(); this.timeoutId = setTimeout(() => { this.longPress.emit(); // 触发长按事件,显示tooltip // 阻止当前触摸事件的默认行为 event.preventDefault(); event.stopPropagation(); // 绑定contextmenu事件,彻底拦截长按菜单 this.elementRef.nativeElement.addEventListener('contextmenu', this.contextMenuListener); }, 500); // 长按阈值可根据需求调整 } @HostListener('touchend') onTouchEnd() { const touchDuration = Date.now() - this.touchStartTime; // 如果是短按(小于长按阈值),移除contextmenu监听,确保锚点正常跳转 if (touchDuration < 500) { this.elementRef.nativeElement.removeEventListener('contextmenu', this.contextMenuListener); } clearTimeout(this.timeoutId); } @HostListener('touchcancel') onTouchCancel() { // 触摸被中断时,清理监听和定时器 this.elementRef.nativeElement.removeEventListener('contextmenu', this.contextMenuListener); clearTimeout(this.timeoutId); } }
关键改动说明:
- 兜底拦截
contextmenu事件:移动端浏览器的长按菜单大多是通过这个事件触发的,直接阻止它才能彻底禁用菜单。 - 区分长短按逻辑:短按的时候移除
contextmenu监听,保证锚点的正常跳转功能不受影响;只有长按触发后才启用拦截。 - 清理资源:在触摸结束或中断时,必须移除监听并清除定时器,避免内存泄漏和后续交互异常。
内容的提问来源于stack exchange,提问作者Gtm
相关产品推荐
相关产品推荐

