根本原因是iOS和Android浏览器对长按触发原生菜单,uni-app的在H5端渲染为故无法避免;可靠禁用需CSS(-webkit-touch-callout: none; user-select: none),并推荐改用原生标签配合手动模拟长按逻辑。

uni-app H5长按图片弹出系统菜单的根本原因
这不是 bug,是 iOS 和 Android 浏览器(尤其是微信、QQ 内置浏览器)的默认行为:长按 会触发原生菜单(“保存图像”“复制”等)。uni-app 的 组件在 H5 端最终渲染为 ,所以逃不开这个机制。关键点在于——@longpress 事件和系统菜单是并行触发的,不是互斥关系。
禁用系统菜单必须用 CSS,JS e.preventDefault() 在多数场景下无效
很多人尝试在 @touchstart 或 @contextmenu 里调用 e.preventDefault(),但在 iOS Safari 和微信内置浏览器中,对 元素的长按菜单拦截成功率极低。真正可靠的是 CSS 层面的声明:
-
-webkit-touch-callout: none:iOS 专属,直接关掉长按呼出菜单 -
user-select: none:标准属性,阻止文本选择,间接抑制菜单触发条件 - 必须同时设置
-webkit-user-select: none等前缀,否则安卓 Chrome 可能不生效
推荐写法(全局生效,但需排除输入类元素):
*
{
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
input,
textarea,
[contenteditable="true"] {
-webkit-user-select: auto !important;
user-select: auto !important;
}
uni-app 中 组件在 H5 端要换成 ![]()
才能生效
uni-app 的 是跨平台封装组件,在 H5 端它内部仍会生成 ,但可能包裹了额外 DOM 节点或内联样式,导致你写的 CSS 无法精准命中。最稳妥的做法是直接使用原生 标签:
- 把
改成 - 确保该
没有被父容器设置pointer-events: none(否则你的自定义长按逻辑也收不到事件) - 如果要用
mode效果(如widthFix),用 CSS 替代:style="width: 100%; height: auto;"
示例:
@@##@@
配合 CSS:.no-context-menu { -webkit-touch-callout: none; user-select: none; }
想保留长按功能?必须手动模拟,且注意滑动冲突
禁用系统菜单后,@longpress 在部分安卓机型上仍不可靠,iOS 更是基本失效。正确做法是用 @touchstart + setTimeout + @touchend / @touchcancel 模拟:
- 在
touchstart启动一个 500–800ms 的定时器 - 在
touchend或touchcancel中清除定时器,避免误触发 - 必须监听
@touchmove并e.preventDefault(),否则用户拖拽时也可能触发长按 - 注意:若页面本身可滚动,需加
@touchmove.stop.prevent阻止穿透,否则滑动时会意外打开菜单
容易被忽略的一点:iOS 上,如果 外层有 position: fixed 或 transform,坐标计算可能偏移,菜单定位失准。建议菜单用 position: fixed + top/left 动态计算,而非 absolute。











