火狐响应式测试模式长按提前触发onCancel及IndexSizeError问题求解
问题1 火狐桌面端移动端测试模式下onCancel被提前触发的解决方案
根本原因
- 你在head中定义的DOM操作逻辑执行时机错误:脚本运行时body还未渲染,
document.getElementById("ItemImage")返回null,导致你写的contextmenu事件绑定、preventLongPressMenu逻辑完全没有生效。 - 火狐响应式设计模式的模拟touch机制优先级高于JS层面的contextmenu阻止逻辑,仅靠JS拦截contextmenu事件无法阻止默认长按菜单触发,而你配置的
use-long-press库默认会在系统上下文菜单触发时执行onCancel回调。 - 你将
use-long-press的detect参数设为both,会同时监听鼠标和touch两类事件,火狐响应式模式下两类事件会同时触发,产生逻辑冲突导致提前取消。
解决方法
- 修正DOM绑定逻辑的执行时机:把你写在head里的DOM操作逻辑放到
DOMContentLoaded事件回调中,确保能拿到对应DOM节点,同时主动调用init函数:
window.addEventListener('DOMContentLoaded', () => { // 把原来的contextmenu绑定、init()调用都放到这里 init() })
- 给长按目标元素加CSS属性
touch-action: none,直接告诉浏览器禁用该区域的所有默认触摸行为(包括长按菜单、缩放、滑动等),优先级比JS拦截更高:
.disable-select { /* 原有属性保留,新增下面一行 */ touch-action: none; }
- 修改
use-long-press的配置:如果仅在移动端使用长按功能,将detect参数改为touch;如果要兼容桌面端,新增cancelOnContextMenu: false配置,避免上下文菜单触发时自动执行onCancel。 - 长按开始时主动清空页面选中内容,避免浏览器默认选中逻辑干扰:
onStart: (event) => { window.getSelection().removeAllRanges() // 原有逻辑保留 }
问题2 IndexSizeError: Selection.getRangeAt: 0 is out of range报错原因
这个报错的触发逻辑非常明确:当代码尝试调用Selection.getRangeAt(0)获取选中内容的范围对象时,当前页面没有任何选中的内容,window.getSelection().rangeCount的值为0,取下标为0的元素自然触发数组越界错误。
对应你的场景:你给元素加了user-select: none禁止选中,同时长按过程中浏览器或者第三方库(包括你使用的use-long-press、火狐响应式模式的模拟touch逻辑)尝试读取选中范围,就会抛出该错误。
解决方法
所有调用getRangeAt的位置先判断是否存在可用的选中范围:
const selection = window.getSelection() if (selection.rangeCount > 0) { const range = selection.getRangeAt(0) // 执行后续逻辑 }
如果是第三方库触发的报错,在长按开始时主动清空选中范围即可避免:
window.getSelection().removeAllRanges()
内容的提问来源于stack exchange,提问作者Jon
相关产品推荐
相关产品推荐

