拖拽之mouseup问题

在实现拖拽功能时遇到一个bug:当鼠标首次点击并拖动滑块后,第二次点击无法触发mouseup事件。问题在于鼠标按下并拖动时会触发文本选择功能,导致mouseup事件未被正确触发。解决办法是在鼠标按下时给body添加onselectstart='return false',鼠标放开时移除,以阻止文本选择。然而,为何第一次正常而第二次不正常仍然是个谜。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

今天做一个拖拽案例,就是滚动条的一部分。当鼠标移动到滑块上并且按下时,给document绑定mousemove事件,当鼠标放开时解除mousemove事件,代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="vue/vue.2.5.js"></script>
    <script src="vue/jQuery.js"></script>
    <style>
        .scale{
            position: absolute;
            left: 100px;
            top: 100px;
            width: 100px;
            text-align: center;
        }
        .slider_box{
            position: relative;
            width: 1px;
            height: 200px;
            background-color: #000;
            margin: 10px auto;
        }
        .slider{
            position: absolute;
            width: 18px;
            height: 8px;
            background-color: #000;
            border-radius: 3px;
            left: -8px;
            cursor: pointer;
        }
    </style>
</head>
<body>
<div id="app">

</div>
<div class="scale">
    <!--只要界面存在其它元素,就会有bug,这是什么原因-->
    <a href="javascript:;" class="add">+</a>
    <div class="slider_box">
        <div class="slider" id="box"></div>
    </div>
    <a href="javascript:;" class="reduce">-</a>
</div>
<script>
    function dragEle(opt){
        //可以来点判断,当调用这个函数时输入参数错误时提示
        if(!opt.dragEle){
            console.log('要拖拽的元素是哪个');
        }
        var dragEle = opt.dragEle;
        var dragWrap = opt.dragWrap;

        //原理,点击元素,获取源位置,移动鼠标,获取目标位置,鼠标移动多少元素移动多少
        var sourcePos = {left:0,top:0};
        var targetPos = {left:0,top:0};
        var elePos = {left:0,top:0};
        //元素宽高为了碰撞检测
        var box = {height:dragWrap.height(),width:dragWrap.width()};
        var son = {height:0,width:0};
        dragEle.mousedown(function(event){
            console.log('begin');
            elePos.left = dragEle.position().left;
            elePos.top = dragEle.position().top;
            sourcePos.left=event.pageX;
            sourcePos.top=event.pageY;
            son.width = dragEle.width();
            son.height = dragEle.height();
            // console.log(event.target.classList);
            $(document).mousemove(function(event){
                targetPos.left = event.pageX;
                targetPos.top = event.pageY;
                //这个elePos为元素位置,点击时获取
                var top = elePos.top + targetPos.top - sourcePos.top;
                //碰撞检测
                if(top<0){
                    top = 0;
                }
                if(top>box.height-son.height){
                    top = box.height-son.height;
                }
                dragEle.css({
                    top: top + 'px'
                })
            });
        });
        $(document).mouseup(function(){
            console.log('off');
            $(document).off('mousemove');
        });
    }
    dragEle({
        dragEle: $('.slider'),
        dragWrap: $('.slider_box')
    });
</script>
</body>
</html>

这时就出现了一个bug,当第一次点击滑块,鼠标移到别的地方时,正常,然后再一次点击滑块时就出现了问题。把js代码简化成下面这样,继续找问题

$('.slider').off('mousedown').on('mousedown',function(ev){
    console.log('down');
    $(document).off('mousemove').on('mousemove',function(ev){
        console.log('move')
    });
});
$(document).off('mouseup').on('mouseup',function(){
    console.log('up');
    $(document).off('mousemove')
});

当第一次点击元素,鼠标横向离开元素(上下离得远也行)放开鼠标能打印up,再一次点击,离开,放开鼠标,不能打印up。百度了好久也找不到,最后问了人才知道,当鼠标按下,并拖动时,还会触发选择功能,就是平时用鼠标选择文本复制。这时放开鼠标,它还是触发了选中其它内容的效果,所以触发不了mouseup;要给body加个 onselectstart="return false" ,然后就没有这个问题了,使用时也就是当按下鼠标时给body加上这个,放开鼠标时给body去掉这个。

但是我还有一个问题,为什么第一次正常,第二回不正常????有哪位大神能告知!!

好了,现在滚动条的一部分已经出来了,接着给它传入回调函数,就可以实现其它功能了,代码形如:

function dragEle(opt){
    //可以来点判断,当调用这个函数时输入参数错误时提示
    var dragEle = opt.dragEle;
    var callback = opt.callback;
    
    dragEle.mousedown(function(){
        $(document).mousemove(function(){
            callback(123)
        });
    });
    $(document).mouseup(function(){
    });
}
function myScroll(forParm) {
    console.log(forParm);
}
dragEle({
    dragEle: $('.slider'),
    callback:myScroll
});
<think>我们正在讨论鼠标事件,特别是mouseup事件。根据引用[2]和引用[4]:- mouseup事件在释放任意鼠标按键时触发。-它发生在鼠标按键被按下(mousedown)之后,当用户释放按键时。触发时机:当鼠标指针在元素上时,按下鼠标按键(mousedown),然后释放按键(mouseup)就会触发mouseup事件。 注意:mouseup事件与click事件的区别在于,click事件实际上是由mousedown和mouseup组合而成的,且要求在同一元素上完成按下和释放。而mouseup只要释放按键就会触发,不论之前是否在同一元素上按下。另外,引用[4]还提到,mouseup事件在鼠标按下抬起之后触发。因此,总结:- mouseup事件:当鼠标按键被释放时触发。 -触发顺序:通常先触发mousedown,然后触发mouseup,如果这两个事件发生在同一元素上,则接着触发click事件。 相关问题: 1. mouseup事件与click事件有什么区别? 2.如何阻止mouseup事件冒泡?3.mouseup事件在拖拽操作中有什么作用? 4.如何通过JavaScript监听mouseup事件?</think>### mouseup 事件详解 **mouseup 事件**是鼠标事件的一种,指当鼠标按键被释放(抬起)时触发的事件。以下是详细说明: #### 触发时机 1. **基础定义** 当鼠标指针位于元素上方时,用户释放任意鼠标按键(左键、右键或中键)会触发该事件[^2][^4]。 例如:$ \text{触发条件} = \{\text{鼠标按键抬起}\} $ 2. **与相关事件的关系** - **与 mousedown 对应**: `mousedown`(按下按键) → `mouseup`(释放按键)构成完整操作[^2][^4]。 $$ \text{事件序列: } \text{mousedown} \rightarrow \text{mouseup} \rightarrow \text{click} $$ - **与 click 的区别**: `click` 需在同一元素上完成 `mousedown` 和 `mouseup`,而 `mouseup` 只需释放按键即可触发(即使释放位置不在初始按下元素上)[^4]。 #### 典型应用场景 1. **拖拽操作** 结合 `mousedown` 和 `mousemove` 实现元素拖拽,`mouseup` 标志拖拽结束[^4]: ```javascript element.addEventListener('mousedown', startDrag); document.addEventListener('mousemove', duringDrag); document.addEventListener('mouseup', endDrag); // 释放时结束拖拽 ``` 2. **自定义交互控件** 如滑动条调整、绘图工具中画笔抬起等[^1][^4]。 3. **组合操作** 与 `keydown` 事件配合实现快捷键功能(例如按住 `Shift` 时释放鼠标)。 #### 注意事项 - **冒泡行为**: `mouseup` 事件会冒泡到父元素(与 `mouseleave` 不同)[^4][^5]。 - **触屏设备**: 在触屏设备上,`mouseup` 可能被误触发(需用 `touchcancel` 处理兼容性)[^3]。 --- ### 相关问题 1. `mouseup` 与 `click` 事件在实际代码中如何区分使用? 2. 如何阻止 `mouseup` 事件在拖拽操作中的默认行为? 3. 移动端触屏事件如何避免误触发 `mouseup`? 4. `mouseup` 事件在哪些常见网页组件中必不可少? [^1]: JavaScript 事件分类之焦点事件与鼠标事件 [^2]: 关于界面的 mousedown、mouseup、click 事件 [^3]: 去除触屏事件连带引发鼠标事件的方法 [^4]: DOM 鼠标事件类型概览 [^5]: JavaScript 鼠标事件监听与触发顺序
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值