设置passive为true后,空函数替换ontouchmove能否可靠阻止默认行为?
问题解答
1. 用空函数替换ontouchmove是否可靠?
不可靠,核心问题有两个:
- 覆盖原有事件逻辑:这种方式是直接替换DOM0级事件处理函数,如果页面中其他代码也通过
document.ontouchmove = xxx绑定了业务逻辑,会被你的空函数完全覆盖,导致依赖touchmove的其他功能直接失效。 - 无法稳定阻止默认行为:空函数返回
undefined,并不会主动阻止浏览器执行touchmove的默认行为(比如页面滚动)。你觉得“可行”大概率是当前场景下的巧合,比如原来的事件监听被覆盖后暂时没有触发默认行为的逻辑,但这不是稳定的解决方案。
2. 不用e.preventDefault()或return false的替代方案?
你的核心矛盾是设置了passive: true后无法在回调里调用e.preventDefault(),以下是几种更可靠的处理方式:
方案一:动态切换事件监听的passive状态
当满足条件时,移除原来的passive: true监听,替换为passive: false的监听来阻止默认行为;不需要时再恢复原监听:
// 保存原有touchmove处理逻辑 const originalTouchHandler = (e) => { // 你原本的passive事件逻辑 }; // 用于阻止默认行为的处理函数 const preventTouchHandler = (e) => { e.preventDefault(); }; // 初始化绑定passive监听 document.addEventListener('touchmove', originalTouchHandler, { passive: true }); function disableScroll() { document.removeEventListener('touchmove', originalTouchHandler); document.addEventListener('touchmove', preventTouchHandler, { passive: false }); } // 可选:恢复滚动的函数 function enableScroll() { document.removeEventListener('touchmove', preventTouchHandler); document.addEventListener('touchmove', originalTouchHandler, { passive: true }); } // 触发条件 if (dragDistanceX > 3 * dragDistanceY) { disableScroll(); }
方案二:用CSS touch-action直接控制
如果你的需求只是阻止页面滚动,完全可以用浏览器原生支持的CSS属性,不需要JS事件干预,性能最优:
/* 定义禁用滚动的类 */ .disable-scroll { touch-action: none; }
然后在JS中通过添加/移除类来触发:
function disableScroll() { document.body.classList.add('disable-scroll'); } function enableScroll() { document.body.classList.remove('disable-scroll'); } // 触发条件 if (dragDistanceX > 3 * dragDistanceY) { disableScroll(); }
方案三:去掉passive: true,按需阻止
如果你的场景中需要阻止默认行为的频率不高,可以直接不设置passive: true,在回调里判断条件后调用e.preventDefault():
document.addEventListener('touchmove', (e) => { // 你的业务逻辑 if (dragDistanceX > 3 * dragDistanceY) { e.preventDefault(); } }, { passive: false });
注意:这种方式会让浏览器无法优化滚动性能,但如果只是特定条件下触发,性能影响可以忽略。
内容的提问来源于stack exchange,提问作者MMF
相关产品推荐
相关产品推荐

