多窗口拖拽异常问题:首个可拖拽窗口释放鼠标后无法停止拖拽
问题分析与解决方案
嗨,刚接触JS/HTML/CSS就能实现窗口标题栏拖拽的效果,已经做得很棒啦!咱们来拆解下你遇到的问题:
你猜的没错,问题核心确实在拖拽结束的document.onmouseup代码段里。每次调用makeDragable函数时,你都用document.onmouseup = function(...)直接赋值新的处理函数——这会彻底覆盖掉之前绑定的函数。当你第二次调用makeDragable处理第二个窗口后,第一个窗口的mouseup逻辑就被替换了,导致第一个窗口释放鼠标时,没法移除它的mousemove监听,自然就停不下来拖拽了。
修复后的代码
只需要修改拖拽结束的绑定方式,用addEventListener替代直接赋值,就能让多个窗口的拖拽结束逻辑共存:
// Draggable Content JS function makeDragable(dragHandle, dragTarget) { let dragObj = null; // 要拖动的对象 let xOffset = 0; // 防止拖动时对象跳转到鼠标位置的偏移量 let yOffset = 0; // 提前获取DOM元素,避免重复查询 const handle = document.querySelector(dragHandle); const target = document.querySelector(dragTarget); handle.addEventListener("mousedown", startDrag, true); handle.addEventListener("touchstart", startDrag, true); /* 设置偏移参数并开始监听鼠标移动 */ function startDrag(e) { e.preventDefault(); e.stopPropagation(); dragObj = target; dragObj.style.position = "absolute"; let rect = dragObj.getBoundingClientRect(); if (e.type=="mousedown") { xOffset = e.clientX - rect.left; yOffset = e.clientY - rect.top; window.addEventListener('mousemove', dragObject, true); } else if(e.type=="touchstart") { xOffset = e.targetTouches[0].clientX - rect.left; yOffset = e.targetTouches[0].clientY - rect.top; window.addEventListener('touchmove', dragObject, true); } } /* 拖动对象逻辑 */ function dragObject(e) { e.preventDefault(); e.stopPropagation(); if(dragObj == null) { return; } else if(e.type=="mousemove") { dragObj.style.left = e.clientX-xOffset +"px"; dragObj.style.top = e.clientY-yOffset +"px"; } else if(e.type=="touchmove") { dragObj.style.left = e.targetTouches[0].clientX-xOffset +"px"; dragObj.style.top = e.targetTouches[0].clientY-yOffset +"px"; } } /* 结束拖动 - 修改核心部分 */ function endDrag(e) { if (dragObj) { dragObj = null; window.removeEventListener('mousemove', dragObject, true); window.removeEventListener('touchmove', dragObject, true); } } // 用addEventListener绑定,避免覆盖之前的处理函数 document.addEventListener('mouseup', endDrag, true); document.addEventListener('touchend', endDrag, true); } makeDragable('#handle_1', '#moveable_1') makeDragable('#handle_2', '#moveable_2')
关键修改点说明
- 替换事件绑定方式:把
document.onmouseup = function(...)改成document.addEventListener('mouseup', endDrag, true),这样每个窗口的endDrag函数都会被独立绑定,不会被后续调用覆盖。 - 补充触摸事件处理:同时给
touchend绑定了结束逻辑,保证触摸设备上的拖拽也能正常停止。 - 优化DOM查询:提前把拖拽手柄和目标元素存到变量里,避免每次事件触发时重复查询DOM,小幅度提升性能。
如果以后担心多个窗口同时拖拽的冲突,可以加一个全局变量跟踪当前正在拖拽的对象,在新拖拽开始时自动结束之前的拖拽过程,不过目前你的需求场景下,上面的修复已经完全够用啦。
内容的提问来源于stack exchange,提问作者elliott hall
相关产品推荐
相关产品推荐

