You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

实现网页拖拽滚动时,如何阻止链接默认跳转?

拖拽滚动场景下阻止链接默认跳转的解决方案

问题背景

基于拖拽滚动脚本实现了网页拖拽滚动功能,同时通过CSS移除了<a>标签和图片的默认可拖拽性,确保鼠标在这些元素上时也能拖拽页面。但拖拽页面后,点击链接时的e.preventDefault()无法阻止链接跳转。

当前使用代码

JavaScript代码

document.addEventListener('DOMContentLoaded', () => {
    let dragging; const pos = {};

    const onClick = (e) => {
      if(!dragging)
        return;
      
      e.preventDefault(); // 无效:原因何在?
      e.stopImmediatePropagation();
    };

    const onMouseMove = (e) => {
        dragging = true;
        window.scroll(0, pos.top - (e.clientY - pos.y));
    };

    const onMouseUp = (e) => {
        dragging = false;
        
        e.target.removeEventListener('mousemove', onMouseMove);
        e.target.removeEventListener('mouseup', onMouseUp);
        e.target.removeEventListener('click', onClick);
    };

    const onMouseDown = (e) => {  
        pos.top = window.scrollY;
        pos.y = e.clientY;

        e.target.addEventListener('mousemove', onMouseMove);
        e.target.addEventListener('mouseup', onMouseUp);
        e.target.addEventListener('click', onClick);
    };

    document.addEventListener('mousedown', onMouseDown);
});

CSS代码

a, img {
  user-drag: none;
  -webkit-user-drag: none;
}

HTML代码

<div style="height:200vh; background:lightblue; padding:1em;">
  <h1>Drag to scroll me</h1>
  
  <a href="//stackoverflow.com" style="background:white; padding:1em">Dragging this link should NOT open the website (but does)</a>
</div>

问题原因

事件触发顺序为mousedown → mousemove → mouseup → click。当前代码在mouseup中立刻把dragging设为false,等click事件触发时,dragging已经是false,导致onClick里的判断不生效,e.preventDefault()根本没执行。

解决方法

方法一:延迟重置拖拽状态

修改onMouseUp函数,用setTimeout延迟重置dragging,确保click事件先完成判断:

const onMouseUp = (e) => {
    // 延迟100ms重置dragging,让click事件先执行判断逻辑
    setTimeout(() => {
        dragging = false;
    }, 100);
    
    e.target.removeEventListener('mousemove', onMouseMove);
    e.target.removeEventListener('mouseup', onMouseUp);
    e.target.removeEventListener('click', onClick);
};

方法二:通过位移区分点击和拖拽(更可靠)

记录鼠标按下时的初始位置,在click事件中判断位移大小,超过阈值则判定为拖拽,阻止链接跳转:

document.addEventListener('DOMContentLoaded', () => {
    let isDragging = false;
    const pos = { top: 0, y: 0, startY: 0 };

    const onClick = (e) => {
        // 位移超过5px判定为拖拽,阻止默认跳转
        if (Math.abs(e.clientY - pos.startY) > 5) {
            e.preventDefault();
            e.stopImmediatePropagation();
        }
    };

    const onMouseMove = (e) => {
        isDragging = true;
        window.scroll(0, pos.top - (e.clientY - pos.y));
    };

    const onMouseUp = (e) => {
        isDragging = false;
        
        e.target.removeEventListener('mousemove', onMouseMove);
        e.target.removeEventListener('mouseup', onMouseUp);
        e.target.removeEventListener('click', onClick);
    };

    const onMouseDown = (e) => {  
        pos.top = window.scrollY;
        pos.y = e.clientY;
        pos.startY = e.clientY; // 记录初始点击位置

        e.target.addEventListener('mousemove', onMouseMove);
        e.target.addEventListener('mouseup', onMouseUp);
        e.target.addEventListener('click', onClick);
    };

    document.addEventListener('mousedown', onMouseDown);
});

两种方法对比

  • 方法一简单修改现有逻辑,但依赖事件队列时序,若浏览器事件触发间隔有差异可能失效;
  • 方法二通过物理位移判断操作意图,更精准,能彻底区分“点击”和“拖拽”,推荐使用。

内容的提问来源于stack exchange,提问作者Simon Ferndriger

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.23 04:06:24